Troubleshooting
CircularDependencyError
Section titled “CircularDependencyError”Error: CircularDependencyError: Circular dependency detected: A -> B -> A
Cause: Two or more services depend on each other either directly or through a chain. The dependency graph cannot be topologically sorted.
Solution: Break the cycle by:
- Extracting the shared dependency into a separate service
- Using
resolve_optional()or lazy injection (factoryparameter) for one direction - Restructuring your domain boundaries
# Before (circular):class A: def __init__(self, b: B) -> None: ...
class B: def __init__(self, a: A) -> None: ...
# After (break with factory):container.singleton(A, A)container.singleton(B, factory=lambda: B())UnresolvableDependencyError
Section titled “UnresolvableDependencyError”Error: UnresolvableDependencyError: Cannot resolve <ServiceType>: not registered
Cause: A constructor parameter type is not registered in the container and cannot be instantiated automatically.
Solution:
- Register the missing type in the appropriate provider:
container.singleton(MyService, MyService())
- If it’s an optional dependency, type-hint it as
Optional[T]or useresolve_optional. - If the dependency is provided by an extension package, ensure that package’s provider is registered with the application.
ContainerValidationError
Section titled “ContainerValidationError”Error: ContainerValidationError: Scope violation: Singleton 'A' depends on scoped 'B'
Cause: A singleton-scoped service has a dependency on a scoped or transient service, which would create a stale reference.
Solution: Either:
- Change
Ato scoped:container.scoped(A, A) - Make
Ba singleton:container.singleton(B, B()) - Use a factory pattern to resolve
Blazily
ModuleVisibilityError
Section titled “ModuleVisibilityError”Error: ModuleVisibilityError: Module 'X' cannot resolve 'Y': not in its exports or global scope
Cause: A module is trying to resolve a service that another module hasn’t exported.
Solution: Either:
- Add the type to the exporting module’s
exportslist - Make the exporting module a
@global_module - Import the exporting module in the consuming module’s
imports
@module( providers=[MyProvider], exports=[MyServiceProtocol], # ← add the type here)class MyModule(Module): passContainerError: Cannot add provider after boot
Section titled “ContainerError: Cannot add provider after boot”Error: RuntimeError: Cannot add provider after boot. State: starting
Cause: Calling app.add_provider() after app.start().
Solution: Register all providers before calling start() or use Application.boot() (which calls start() after setup):
# Correct:async with Application.boot(providers=[MyProvider()]) as app: ...
# Wrong:app = Application()await app.start()app.add_provider(MyProvider()) # RuntimeErrorContainerError: Frozen container
Section titled “ContainerError: Frozen container”Error: ContainerError: Cannot register service: container is frozen
Cause: Attempting to call singleton() / transient() / scoped() on a frozen container.
Solution: All registration must happen during Provider.register(). Provider.boot() can resolve but not register new services.
class MyProvider(Provider): async def register(self, container: ContainerRegistrarProtocol) -> None: container.singleton(MyService, MyService()) # ✅ OK
async def boot(self, container: BootContainerProtocol) -> None: container.singleton(OtherService, OtherService()) # ❌ Container frozenConfigurationError: debug=True in production
Section titled “ConfigurationError: debug=True in production”Error: ConfigIssue: debug=True is not allowed in production
Cause: Running with debug: true in the production environment.
Solution: Set debug: false or remove the LEX_DEBUG env var in production environments. Run config.validate_for_environment() at startup:
config = LexigramConfig.from_yaml()issues = config.validate_for_environment()if issues: for i in issues: print(f"Config error: {i.message}")UnwrapError
Section titled “UnwrapError”Error: UnwrapError: Called unwrap() on an Err value
Cause: Calling result.unwrap() without first checking result.is_ok().
Solution: Always check before unwrapping:
result = await service.find(user_id)if result.is_ok(): user = result.unwrap()else: error = result.unwrap_err()Or use safe accessors:
user = result.unwrap_or(default_user)message = result.match( ok=lambda u: f"Found {u.name}", err=lambda e: f"Error: {e}",)SecretNotFoundError
Section titled “SecretNotFoundError”Error: SecretNotFoundError: Required secret 'DATABASE_PASSWORD' is missing
Cause: A secret registered via app.register_secrets() is empty or unavailable.
Solution: Ensure the secret is set in the environment or secret store, or register it with a non-empty value:
app.register_secrets({"DATABASE_PASSWORD": os.environ["DATABASE_PASSWORD"]})Debug Tips
Section titled “Debug Tips”-
Enable debug logging at boot:
config = LexigramConfig.from_env_profile()config.debug = Trueapp = Application(name="my-app", config=config) -
Dump container registrations:
app.container.dump_registrations()app.container.log_registrations() -
Validate before boot:
issues = app.container.validate()if issues:print("Validation issues:", issues) -
Check registered providers:
for p in app.providers:print(f"{p.name}: {p.state}")