Skip to content

ValidationFailedError

Symptom

Raised by Container.validate(). Its message is one line naming each kind of issue with its count, followed by a link to this page. It is an ExceptionGroup, so a traceback shows each issue in full below that line:

  + Exception Group Traceback (most recent call last):
  |   ...
  | modern_di.exceptions.container.ValidationFailedError: Container.validate() found 2 issue(s): ArgumentResolutionError (1), InvalidScopeDependencyError (1)
  | See: https://modern-di.modern-python.org/troubleshooting/validation-failed-error/
  +-+---------------- 1 ----------------
    | modern_di.exceptions.resolution.ArgumentResolutionError: Argument missing of type <class 'myapp.providers.Missing'> cannot be resolved. Trying to build dependency <class 'myapp.providers.NeedsMissing'>.
    | Did you mean:
    |   - NeedsMissing (similar name, scope=APP)
    | See: https://modern-di.modern-python.org/troubleshooting/argument-resolution-error/
    +---------------- 2 ----------------
    | modern_di.exceptions.registration.InvalidScopeDependencyError: Provider at a deeper scope reached through this chain:
    |   APP      Shallow (myapp.providers:15)
    |   REQUEST  └─> Deep (myapp.providers:12)
    |   caused by: Shallow (scope APP) declares parameter 'deep' typed as a provider of Deep at deeper scope REQUEST. A provider cannot depend on a deeper-scoped provider.
    | See: https://modern-di.modern-python.org/troubleshooting/scope-chain/
    +------------------------------------

logger.exception prints the same tree. A plain print(exc) or str(exc) gives only the summary line and the See: line.

Cause

The provider graph has one or more problems. validate() walks the whole graph in one pass and collects every issue, so .exceptions may hold several kinds at once. Each entry is one of these:

Fix

Read the traceback or inspect .exceptions, then fix each issue as its own page describes:

try:
    container.validate()
except exceptions.ValidationFailedError as exc:
    for error in exc.exceptions:
        print(type(error).__name__, error)

To handle one kind of issue and let the rest propagate, use except*:

try:
    container.validate()
except* exceptions.ArgumentResolutionError as group:
    for error in group.exceptions:
        print("unresolvable parameter:", error.parameter_name)

What except* does not catch is raised again as a ValidationFailedError holding only the remaining issues.

Nothing validates the graph for you, not even construction, open() or resolve(). Call validate() at startup, before the first real request, so graph bugs fail there in one error.

See also