Skip to content

[Defect]: traverseSchema lacks cycle detection and produces ambiguous dot paths #832

@Mehrn0ush

Description

@Mehrn0ush

Describe the defect

traverseSchema currently has two reliability/diagnostic issues:

  • Ambiguous path output: It builds paths using dot-notation (${path}.${k}), which becomes ambiguous when a key contains . or other non-identifier characters. Example: a literal key "a.b" is reported as $.a.b (looks like nested keys).
  • No cycle detection: If a schema object becomes circular in-memory (e.g., programmatic construction, loader back-references, alias graphs), traversal can recurse indefinitely and crash with Maximum call stack size exceeded.

Scope: tools/src/main/js/linter/index.js only.

Proposed fix

  • Add stack-based cycle detection using a WeakSet of nodes on the current recursion path (add on entry, remove on unwind) so only true cycles are skipped while shared references (DAGs) remain traversable.
  • Introduce safe path joining:
    • dot notation for simple identifiers
    • bracket notation for non-identifier keys (e.g. $["a.b"])

Optional hardening (kept backward-compatible):

  • Add an opt-in maxDepth guard (default Infinity) with an onDepthLimit hook so truncation is never silent when enabled.

Alternatives considered

  • Implement cycle detection only (leave paths unchanged) — avoids crashes but keeps ambiguous diagnostics.
  • Implement safe paths only (leave cycles unchanged) — improves diagnostics but doesn’t prevent crashes.
  • Add depth-only protection without cycle detection — may help with deep recursion but does not address true cycles.

Additional context

Observed while working on the 2.0 schema tooling

  • This affects issue paths emitted by all checks that rely on traverseSchema.
  • Backwards compatibility: path formatting changes only for keys that are not simple identifiers; default traversal behavior remains unchanged unless a finite maxDepth is explicitly set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions