swagger-api / swagger-api/swagger-parser
[Bug]: Regression: resolveFully fails when components key does not match external file basename
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 867
- Forks
- 560
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 7
Description
Description
swagger-parser 2.1.48 reports a false resolution error when parsing an OpenAPI 3.0 document with ParseOptions#setResolveFully(true) and setValidateExternalRefs(true).
The document externalizes a schema under a components key (Foo-status) that does not case-fold-match the external file basename (fooStatus.json). A nested model file references the declared key via #/components/schemas/Foo-status.
- What we're parsing: OpenAPI 3.0.3 spec split across
api.json+ external JSON model files (common codegen layout). - Spec version: OpenAPI 3.0 (3.0.3 in repro).
- Parser behavior: Returns a non-null
OpenAPI, but adds an error message toSwaggerParseResult#getMessages(). Callers that treat any parser message as fatal (e.g. codegen validation) fail CI even though the model is structurally valid.
2.1.47 accepts the identical input with messageCount=0.
Affected Version
io.swagger.parser.v3:swagger-parser-v3 2.1.48
Earliest version the bug appears in (if known): 2.1.48 (2.1.47 passes with identical input)
Steps to Reproduce
- Use the attached
swagger-parser-repro-2.1.48.zip(standalone Gradle project; genericdemonames only). - Run
./run-repro.sh(orgradle -q classes && java -cp "$(gradle -q printRuntimeClasspath)" demo.ParseDemo). - Observe parser messages.
Minimal schema shape (same files in both zips):
schemas/api.json — registers external schema by display name:
"components": {
"schemas": {
"Foo-item": { "$ref": "./models/fooItem.json" },
"Foo-status": { "$ref": "./models/common/fooStatus.json" }
}
}
schemas/models/fooItem.json — nested ref to declared key:
"status": { "$ref": "../api.json#/components/schemas/Foo-status" }
schemas/models/common/fooStatus.json — simple string enum (ALPHA, BETA).
Java driver (ParseDemo.java):
ParseOptions options = new ParseOptions();
options.setResolveResponses(true);
options.setValidateExternalRefs(true);
options.setResolveFully(true);
SwaggerParseResult result =
new OpenAPIV3Parser().readLocation(apiJson.getAbsolutePath(), null, options);
Compare with swagger-parser-repro-2.1.47.zip (only dependency version differs).
Expected Behavior
SwaggerParseResult#getMessages() is empty (as in 2.1.48's predecessor 2.1.47). Externalized schemas whose registered components key differs from the file basename (e.g. Foo-status + fooStatus.json) should resolve under full-resolve validation.
Actual Behavior
2.1.48 adds an error message:
Could not find components/schemas/fooStatus in contents of ./api.json
The registered key is Foo-status (lowercase foo-status). The parser appears to look up fooStatus from the file basename instead of the declared components key.
getOpenAPI() is non-null, but the error message breaks downstream tooling that fails on any parser message.
Logs / Stack Traces
2.1.47 (swagger-parser-repro-2.1.47.zip):
messageCount=0
RESULT: openAPI parsed
schema keys: [Foo-item, Foo-status, fooItem, fooStatus]
2.1.48 (swagger-parser-repro-2.1.48.zip):
messageCount=1
MESSAGE: Could not find components/schemas/fooStatus in contents of ./api.json
RESULT: openAPI parsed
schema keys: [Foo-item, Foo-status, fooItem, fooStatus, Foo-status_1]
Environment
- Java version: OpenJDK 21 (repro also works on Java 17+)
- Build tool: Gradle 9.7
- OS: macOS (Darwin)
Additional Context
Attached zips (no vendor-specific identifiers):
swagger-parser-repro-2.1.47.zip— passing baselineswagger-parser-repro-2.1.48.zip— failing repro
Regression introduced between 2.1.47 and 2.1.48 on the same unchanged OpenAPI input.
Checklist
- I have searched the existing issues and this is not a duplicate.
- I have provided sufficient information for maintainers to reproduce the issue.
Likely regression point (2.1.47 → 2.1.48)
Compared v2.1.47...v2.1.48 (12 commits). The failure matches external schema resolution changes in:
- Primary suspect:
f605c3c— PR #2382 (fixes #2055), merged 2026-08-20- Rewrote
ExternalRefProcessorand addedComponentNameAllocator - External schemas are allocated via
allocateSchemaName()usingcomputeDefinitionName($ref)(file basename, e.g.fooStatus) rather than the registered components key (Foo-status) _Nsuffix collision behavior explains extra keyFoo-status_1in 2.1.48 output
- Rewrote
- Possible contributor:
0255d18— PR #2383 (fixes #1961), merged 2026-08-25- Root-document back-reference handling in
ResolverCache - Repro includes nested
../api.json#/components/schemas/Foo-statusfrom an external model file
v2.1.47passes;v2.1.48fails on identical input with:
Could not find components/schemas/fooStatus in contents of ./api.json
Compare: https://github.com/swagger-api/swagger-parser/compare/v2.1.47...v2.1.48
- Root-document back-reference handling in
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ExternalRefProcessor and ComponentNameAllocator, then inspect ResolverCache for the root-document back-reference path described in the report. Run the attached repro with the 2.1.47 and 2.1.48 baselines and compare the external schema resolution behavior. Done means the 2.1.48 input produces no parser messages while preserving the declared Foo-status component key.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100