Skip to content
wiki edited this page Sep 4, 2026 · 1 revision

FAQ

Why does resolving my scoped type from the container fail?

Because a scoped value built from the root would have no owning scope, and nothing would ever close it. Resolve it from container.NewScope() — or, in a rex handler, from ctx.Resolver(). See ErrScopedFromRoot.

My factory closes over the container and my scoped dependency fails. Why?

Because the captured container is the root. Take a dix.Resolver parameter instead: for a scoped registration, the resolver you are handed is the scope.

c.Scoped(func(r dix.Resolver) *Repo { ... }) // r is the scope

Can a singleton depend on a scoped value?

No, and it should not want to. A singleton outlives every scope, so holding a scoped value would keep the first request's transaction alive forever. Resolve the scoped value at the point of use instead, and pass it in.

Does the order of registrations matter?

No, as long as everything is registered before the first resolve. Construction is lazy, so a singleton factory may depend on anything registered before the first resolve, not before the factory.

How do I register two implementations of one interface?

You can — and ResolveAll will return both. But Resolve on that interface will then fail with ErrAmbiguousResolution rather than pick one at random. If exactly one should win, register only that one, or resolve the concrete type.

Are singletons closed on shutdown?

No. Only Scope.Close closes anything, and only scoped instances. Close singletons in the code that owns application shutdown.

Are transients closed when the scope closes?

No. The scope tracks scoped instances only. A transient that owns a resource is owned by whoever resolved it.

Instance rejected my value. Why?

nil and functions are refused. A function passed to Instance is almost always a factory that meant to go to Singleton, so it fails loudly rather than registering a value of func type that nothing will ever match.

Is it safe to register while the application is serving?

Mechanically, yes — the container is fully guarded. Practically, the value will be invisible to any resolve that already happened, and a route registered late in rex is refused outright. Register during wiring.

How do I mock a dependency in a test?

Register the mock's concrete type with Instance and let interface matching do the rest; see RecipesSwapping a dependency for a test. Use a fresh container per test.

Why does my program hang instead of reporting a cycle?

It is not hanging, it is recursing — A needs B needs A. There is no cycle detection; see Limitations.

Should my extension import dix?

No. rextension/di declares the same Container, Resolver and Scope contract, and rextension re-exports all three, so extension code writes rextension.Resolver and depends only on the contract module. dix is the implementation the framework happens to use.

Clone this wiki locally