Skip to content

Fix spurious additionalProperties leaf over a declared member's own failure (#175) - #176

Merged
rasuvaeff merged 1 commit into
masterfrom
fix/175-spurious-additional-properties
Oct 17, 2026
Merged

rasuvaeff merged 1 commit into
masterfrom
fix/175-spurious-additional-properties

Conversation

@rasuvaeff

Copy link
Copy Markdown
Owner

Fixes #175

A closed object (additionalProperties: false) whose declared member fails its own subschema received an extra additionalProperties violation of the parent over the member's own failure. The verdict never moved; the reader was told to delete a member that exists.

Cause

The backend marks a member as evaluated only when the properties keyword passes (PropertiesKeyword::validate() calls addCheckedProperties() on the success path alone). A declared member failing its own subschema therefore still counts as unchecked when additionalProperties runs, and false reports it as additional.

Fix

SchemaValidator::leaf() drops such a leaf: a member the sibling properties map declares, or one of its patternProperties patterns matches (same regex semantics as the backend's Helper::patternToRegex), is not additional. An undeclared member keeps its leaf; a member failing the object form of additionalProperties keeps its leaf — there the backend itself judges the flagged members against the added schema, so what it reports there is real.

Repro (from the issue)

  • {"a":[]} against a closed object with properties.a: {type: array, minItems: 1} — before: $.a minItems and a spurious $ additionalProperties; after: the member's failure only.
  • {"a":[],"b":1} — the genuine $ additionalProperties for b survives.

Tests

  • SchemaValidatorTest::closedObjectDoesNotReportItsDeclaredMemberAsAdditional() — the three bodies under failures(), the patternProperties-declared shape, nested closed objects, and the untouched object form.
  • ContractTest counts updated where they pinned the spurious leaf at every depth of a recursive tree (#181 was reached through those counts, response side included).

Gates

  • composer build green (validate, normalize, require-checker, cs, psalm, 969 tests).
  • composer mutation — covered-code MSI 92%, the escaped set unchanged; every mutant of the new filter is killed by the new test.
  • composer rector reports one pre-existing complaint on master itself (RepeatedOrEqualToInArrayRector on a dependency-diff); not addressed here to keep the PR scoped.

Corpus

bin/record-openapi-corpus --check is already stale on master (patternLabels cases; the generator's zoo drifted from the fixture). Verdicts do not move in this change, so re-recording stays outside this PR.

@rasuvaeff rasuvaeff added the bug Something isn't working label Oct 17, 2026
@rasuvaeff rasuvaeff self-assigned this Oct 17, 2026
@coderabbitai

coderabbitai Bot commented Oct 17, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d119c373-cb4f-4105-9688-33d8324bac41
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rasuvaeff
rasuvaeff merged commit b9c0911 into master Oct 17, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A failing declared property also reports a spurious additionalProperties violation on its parent

1 participant