Repository navigation
[Bug]: Regression: resolveFully fails when components key does not match external file basename #2399
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 fix: External Refs with same name are ignored (#2055) #2382 (fixes External Refs with same name are ignored #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 fix: Fix duplicate schemas from root document back-references (#1961) #2383 (fixes Duplicated schemas produced when shared schema references local schema #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: v2.1.47...v2.1.48
- Root-document back-reference handling in
Activity
jimshowalter commentedon Sep 3, 2026
swagger-parser-repro-2.1.47.zip
swagger-parser-repro-2.1.48.zip
goutamadwant commentedon Sep 4, 2026
@jimshowalter I reproduced this on current
masterusing the attached sample and bisected the regression to #2383. Root back-references are resolved correctly but then pass through component-name allocation again, producingFoo-status_1and the invalid basename-derived lookup. I prepared a fix with #2400. Can you review and let me know if there any suggestions or comments? thanks!jimshowalter commentedon Sep 4, 2026
I reproduced this with our OpenAPI schema (declared component key
Foo-status, external filefooStatus.json, nested back-ref fromfooItem.jsonvia../api.json#/components/schemas/Foo-status) and it matches the reported failure on swagger-parser 2.1.48 withresolveFully+validateExternalRefs— we seeCould not find components/schemas/fooStatus in contents of ./api.json. I reviewed #2400 and it looks correct to me: bisecting to the root back-reference path in #2383 and then skipping component-name re-allocation when a ref resolves from the root snapshot directly explains both the bogus basename lookup and the suffixed duplicate key (Foo-status_1). I also applied the patch locally via class shadowing in our codegen plugin and verified that generated model code is unchanged, so this should be a safe fix for multi-file OpenAPI specs where component keys don't match external filenames. Happy to help test a release candidate once it lands.