Repository navigation
Conversation
Reference siblings are ignored by the OAS 3.0 schema check, so schemas reachable only through a local reference (next to a root $ref, or under a non-schema key such as components) were no longer checked. Follow reachable JSON pointer references from the root and check targets the structural check did not cover. References that depend on runtime resolution context are left to instance validation: external and anchor references, references inside a subschema with its own id, targets declaring another dialect, and shortcut calls with a legacy resolver or a root $schema.
evolve runs on every descend; avoid the Mapping ABC check for plain dicts and test the rarer $schema key first.
p1c2u
force-pushed
the
fix/oas30-ref-schema-check
branch
from
November 9, 2026 20:10
cfe16c9 to
4bdf8a4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ignore reference siblings during OAS 3.0 schema checks
In OpenAPI 3.0 an object with
$refis a Reference Object, and "any properties added SHALL be ignored" (OAS 3.0.3, Reference Object). The OAS 3.0 validators already ignore these siblings during instance validation (ignore_ref_siblings). Two places still applied them:$ref. Valid documents such as{"$ref": "#/definitions/x", "description": 5}were rejected withSchemaError, including throughvalidate().evolve()picks a validator class from$schema. A$schemanext to a$refswitched that part of the schema to another dialect and dropped OpenAPI semantics such asnullable.Changes
Reference-aware schema check. The OAS 3.0 validators (
OAS30Validator,OAS30StrictValidator,OAS30ReadValidator,OAS30WriteValidator) check schemas against a private wrapper of the Draft 4 metaschema. Objects with$refonly need a string$ref; every other object is checked as before. Strict/Read/Write keep their previous Draft 4 format checker defaults.evolve()keeps the OAS 3.0 class when$refand$schemaappear together, also forenforce_properties_required=True. Anidnext to$refno longer counts as a scope id either.Local reference targets are checked. Once siblings are ignored, schemas reachable only through a local reference (next to a root
$ref, or under a non-schema key such ascomponents) would no longer be checked.check_schemanow follows reachable#/#/...JSON pointer references from the root and runs the same check on any target the structural pass did not cover. Each target is checked once, and recursive references terminate.The following are left to instance validation, because they depend on runtime resolution context:
id$schemavalidate()calls with a legacyresolveror a root$schemacheck_schema(..., check_references=False)turns the target check off.evolve()overhead reduced. The wrapper from (2) runs on every descend, so the commondictcase skips theMappingABC check.Docs describe the OAS 3.0
$refbehaviour indocs/validation.rst.Behaviour changes
$ref, e.g.{"$ref": ..., "minLength": "x"}SchemaError$schemanext to$ref$refunder a non-schema keySchemaErrordefinitionsthat nothing referencesSchemaErrorSchemaError(unchanged)The third row makes checks stricter: a document that passes today can now raise
SchemaErrorif a local$refpoints at a malformed schema. Release notes should mention it.OAS 3.1 and 3.2 validators are unchanged and still apply
$refsiblings, as JSON Schema 2020-12 requires.Performance
Best of 5 runs, same machine, Python 3.14, jsonschema 4.26.0:
check_schema, 300 cross-referencing definitionsThe remaining validation overhead comes from the
evolve()wrapper in (2).Not in scope
idvalues inside ignored siblings can still breakreferencing's registry crawl when an unresolved URI reference triggers discovery. This already happens on master and is better fixed in its own PR.idscoping arguably should not apply at all. Dropping it would break existing users and needs a deprecation cycle first.Testing
pytest: 325 passed, 9 skipped (master: 277 passed, 6 skipped). Also passes with the minimum supportedjsonschema==4.19.1, apart from the 3 discriminator tests that already fail on master with that version.tests/unit/test_oas30_reference_targets.py: 31 tests covering transitive and escaped pointers, recursion, unresolvable and non-pointer refs,idscopes, foreign dialects, legacy resolvers,enforce_properties_required, and dedup of already-covered targets._references.pyhas 97% coverage.black,isort,flynt,pyupgrade --py36-plus,deptryand the Sphinx docs build (-n -W) pass.mypyreports no new errors; the 2 errors in_regex.pyalready exist on master.