Skip to content

fix(resolver): detect $ref cycles to ancestors of resolved subtrees - #4304

Closed
RobertHebel wants to merge 1 commit into
swagger-api:mainfrom
RobertHebel:fix/resolver-subtree-ancestor-cycles
Closed

RobertHebel wants to merge 1 commit into
swagger-api:mainfrom
RobertHebel:fix/resolver-subtree-ancestor-cycles

Conversation

@RobertHebel

@RobertHebel RobertHebel commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

The OpenAPI 3.1 and 3.2 ApiDOM strategies seeded the dereference lineage with the pathDiscriminator fragment only, so a $ref from the fragment to one of its ancestors was not detected as a cycle. For a recursive Schema Object, e.g. Node with children.items: { $ref: '#/components/schemas/Node' }, SwaggerClient.resolveSubtree, the path Swagger UI resolves through:

  • threw RangeError: Maximum call stack size exceeded for ['components','schemas','Node','properties'] and […,'properties','children'];
  • returned null for […,'children','items'].

Fix: both strategies seed the lineage with the document root and every element along pathDiscriminator. Such a $ref now resolves to an absolute $ref (https://…#/components/schemas/Node), as cycles do when the whole document is resolved.

Tests: resolveSubtree on those paths, on a $ref to an ancestor two levels up, and SwaggerClient.resolve with pathDiscriminator, for 3.1 and 3.2. All of them fail on main. Existing snapshots are unchanged.

Found while reviewing the JSON Schema 2020-12 strategy (#4306), which has the same fix for its own strategy.

🤖 Generated with Claude Code

The OpenAPI 3.1 and 3.2 strategies seeded the dereference lineage with the
pathDiscriminator fragment only, so a $ref from the fragment to one of its
ancestors was not detected as a cycle. A recursive Schema Object such as
Node with children.items { $ref: '#/components/schemas/Node' } overflowed
the stack when resolveSubtree, Swagger UI's resolution path, resolved
['components', 'schemas', 'Node', 'properties'] or
[..., 'properties', 'children'], and returned null for
[..., 'children', 'items']. Seed the lineage with the document root and
every element along the pathDiscriminator, so such a $ref resolves to an
absolute $ref, as cycles do when the whole document is resolved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@robert-hebel-sb

Copy link
Copy Markdown
Contributor

Superseded: recreated with commits cherry-picked onto latest main.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants