Skip to content

fix: do not run nested visitors with a stale parent on shared $refs - #3038

Open
vadyvas wants to merge 1 commit into
mainfrom
fix/walker-stale-parent-shared-refs
Open

fix: do not run nested visitors with a stale parent on shared $refs#3038
vadyvas wants to merge 1 commit into
mainfrom
fix/walker-stale-parent-shared-refs

Conversation

@vadyvas

@vadyvas vadyvas commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What/Why/How?

operation-parameters-unique reported a duplicate parameter that is not there. It happens when the same path item is reused through $ref, for example from two callbacks, and the reported location points at an operation that has no parameters at all.

The reason is in the walker. Two $refs to the same path item resolve to one object, so the walker enters it twice. On the second entry it does not call the rule's enter hooks again, because it already called them for that node — but it still calls the rule's nested Parameter visitor. So the visitor runs with the state and the parent location left over from the first entry, and reports a parameter it had already counted.

Added a guard: a nested visitor now runs only if the node its parent hook sits on is the node the walker is really inside. On the second entry the Parameter visitor stays quiet, and the rule reports only what it actually saw. operation-parameters-unique is not the only rule with this shape — spec-querystring-parameters had the same problem.

Reference

Closes #2829

Testing

Screenshots (optional)

x-signature is declared once, in one list:

paths:
  /sample:
    get:                                  # no parameters here
      callbacks:
        onEventA:
          'https://callbacks.example.com/a':
            $ref: '#/components/pathItems/notify'
        onEventB:
          'https://callbacks.example.com/b':
            $ref: '#/components/pathItems/notify'
components:
  pathItems:
    notify:
      post:
        parameters:
          - in: header
            name: x-signature            # declared once, used in both callbacks

Before:

validating openapi.yaml using lint rules for api 'main'...
[1] openapi.yaml:9:7 at #/paths/~1sample/get/parameters/0

Operations must have unique `name` + `in` parameters. Repeats of `in:header` + `name:x-signature`.

 7 |   /sample:
 8 |     get:
 9 |       operationId: getSample
   |       ^^^^^^^^^^^^^^^^^^^^^^
10 |       summary: example summary
   |       ^^^^^^^^^^^^^^^^^^^^^^^^

Error was generated by the operation-parameters-unique rule.

❌ Validation failed with 1 error.

After:

validating openapi.yaml using lint rules for api 'main'...
openapi.yaml: validated in 4ms

Woohoo! Your API description is valid. 🎉

Check yourself

  • This PR follows the contributing guide
  • All new/updated code is covered by tests
  • Core code changed? - Tested with other Redocly products (internal contributions only)
  • New package installed? - Tested in different environments (browser/node)
  • Documentation update has been considered

Security

  • The security impact of the change has been considered
  • Code follows company security practices and guidelines

Note

Medium Risk
Changes core document-walking logic used by every lint rule; behavior is narrowly scoped with new tests, but regressions in visitor ordering or ref handling are possible.

Overview
Fixes false duplicate-parameter errors when the same path item is referenced from multiple $refs (e.g. two callbacks pointing at #/components/pathItems/notify). Rules like operation-parameters-unique could report duplicates on an operation that has no parameters, because the walker re-entered the shared resolved object without re-running parent enter hooks but still fired nested Parameter visitors with leftover parent state.

The OpenAPI document walker now tracks the resolved node currently being walked per node type (walkingNodeByType). A nested visitor is only activated when the parent hook’s stored node matches that active node, so the second entry through a shared $ref does not run nested visitors with a stale parent.

Unit tests cover shared path items in callbacks and nested rules beside $ref siblings; an e2e fixture confirms lint passes for the callback reuse scenario.

Reviewed by Cursor Bugbot for commit 5467388. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5467388

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@redocly/cli Patch
@redocly/openapi-core Patch
@redocly/client-generator Patch
@redocly/respect-core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vadyvas

vadyvas commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@cursor review

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 77.33% (🎯 77%) 11675 / 15096
🔵 Statements 77.43% (🎯 77%) 12499 / 16142
🔵 Functions 81.43% (🎯 81%) 2355 / 2892
🔵 Branches 71% (🎯 70%) 8587 / 12093
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/core/src/walk.ts 98.27% 97.46% 85% 98.77% 221, 236, 466
Generated in workflow #11293 for commit 5467388 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Performance Benchmark (Lower is Faster)

CLI Version Bundle Lint Check Config
cli-latest ▓ 1.01x ± 0.01 ▓ 1.00x (Fastest) ▓ 1.01x ± 0.01
cli-next ▓ 1.00x (Fastest) ▓ 1.00x ± 0.01 ▓ 1.00x (Fastest)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5467388. Configure here.

@vadyvas
vadyvas marked this pull request as ready for review August 11, 2026 16:15
@vadyvas
vadyvas requested review from a team as code owners August 11, 2026 16:15
@vadyvas vadyvas self-assigned this Aug 11, 2026
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.

Linter reports duplicate parameters when multi-referencing path items

1 participant