Skip to content

Iterator error contexts lose parent links and absolute paths #1584

Description

@GreedyC

Problem

Passing an iterator as ValidationError(context=...) retains its children, but does not set their parent. The iterator is consumed by self.context = list(context), then iterated again when assigning parents. This also affects SchemaError.

from jsonschema.exceptions import ValidationError

child = ValidationError("child", path=["name"], schema_path=[0, "type"])
parent = ValidationError(
    "parent",
    path=["record"],
    schema_path=["properties", "record", "anyOf"],
    context=iter([child]),
)
print(parent.context == [child])  # True
print(child.parent is parent)    # False (expected True)
print(child.json_path)           # $.name (expected $.record.name)

Lists and tuples assign the parent correctly. Setting parents from the stored self.context instead of the original iterable should preserve the same behavior for one-shot iterators.

Reproduced on main (51cd75e39), macOS, Python 3.12.13. A regression test fails for iterator contexts with both error classes and passes for list/tuple contexts.

Investigated with Codex assistance.

Activity

  1. GreedyC commented on Oct 2, 2026

    @GreedyC
    Author

    A one-line fix and regression tests are ready at GreedyC/jsonschema@19ddb83. The full suite passes on Python 3.10 and 3.12 (8,298 passed, 232 skipped each), plus Ruff and both mypy checks.

    PR creation is restricted to collaborators in this repository, so no PR was opened. Leaving the patch here in case it is useful; the iterator tests fail before the fix and cover both error classes.

  2. DawnofGenX commented on Oct 5, 2026

    @DawnofGenX

    I'd like to work on this.

    The issue is that passing an iterator as ValidationError(context=...) retains its children, but does not set their parent. The iterator is consumed by self.context = list(context), then iterated again when assigning parents.

    The fix is to set parents from the stored self.context instead of the original iterable, which should preserve the same behavior for one-shot iterators.

    I'll add a regression test and implement the fix.

  3. simpleqt commented on Oct 6, 2026

    @simpleqt

    Confirmed on main (9eeeddb), including the SchemaError case (shared _Error.__init__).

    I have a prepared fix and regression test on a branch of my fork: main...simpleqt:jsonschema:sq/iterator-context-parents

    The change iterates the already-stored self.context instead of the original one-shot iterable:

             self.context = list(context)
             ...
    -        for error in context:
    +        for error in self.context:
                 error.parent = self

    Attempting to open a pull request from the fork is currently rejected with "does not have the correct permissions to execute CreatePullRequest", which looks like repository interaction limits — so if that's intentional and in effect, feel free to take the patch from the branch directly (single commit, ruff clean, new test in TestErrorInitReprStr fails before / passes after, full suite otherwise unchanged: 7830 passed, 700 skipped).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions