Repository navigation
Description
Description
With the root document in a subdirectory, a relative $ref inside an external path item gets rebased twice. The path item has to sit two directories below the root's parent. The resolved ref then points at a file that does not exist, and with resolve=true the parser reports Unable to load RELATIVE ref. openapi-generator 7.27.0 (which bundles 2.1.48) fails spec validation on it. 2.1.47 resolves the same files.
Affects OpenAPI 3.0 (seen with 3.0.3). Path templates in the fragment ({id}) make no difference, and neither does writing the inner ref as ./schemas.yaml.
Affected Version
2.1.48
Earliest version the bug appears in (if known): 2.1.48 (2.1.47 works)
Steps to Reproduce
-
Create three files:
api/openapi.yaml(the root document):openapi: 3.0.3 info: title: root document one directory below the path items version: '1' paths: /items: $ref: '../domain/sub/paths.yaml#/paths/~1items'
domain/sub/paths.yaml:paths: /items: post: operationId: createItem requestBody: content: application/json: schema: $ref: '../../domain/sub/schemas.yaml#/components/schemas/ItemRequest' responses: '200': description: ok
domain/sub/schemas.yaml:components: schemas: ItemRequest: type: object properties: name: type: string
-
Parse
api/openapi.yamlwithParseOptions.setResolve(true)(new OpenAPIParser().readLocation(...)orOpenAPIV3Parser). -
Look at the request body schema
$refand the messages.
Expected Behavior
As in 2.1.47: the request body schema is #/components/schemas/ItemRequest, the component is resolved, no messages.
Actual Behavior
The request body schema is ../domain/domain/sub/schemas.yaml#/components/schemas/ItemRequest, no component is added, and the result carries the message below.
| Variant | 2.1.47 | 2.1.48 |
|---|---|---|
| Root one directory down, path item two down (above) | ok | ../domain/domain/sub/schemas.yaml |
Same with {id} in the path |
ok | same |
Inner ref written ./schemas.yaml |
ok | same |
Inner ref into another directory, ../../shared/schemas.yaml |
ok | ../domain/shared/schemas.yaml |
Root document at the top (./domain/sub/paths.yaml) |
ok | ok |
Path item one directory down (../domain/paths.yaml, inner ../domain/schemas.yaml) |
ok | ok |
Logs / Stack Traces
Unable to load RELATIVE ref: ../domain/domain/sub/schemas.yaml path: /path/to/api
Environment
- Java version: OpenJDK 17 and 25
- Build tool: Gradle 9 (openapi-generator-gradle-plugin 7.27.0), Maven 3.10
- OS: macOS
Additional Context
The ref is rebased twice:
ExternalRefProcessor.processRefToExternalPathItem->processPathItem->processRefSchemaObject->processRefrewrites it relative to the root document:join("../domain/sub/paths.yaml", "../../domain/sub/schemas.yaml")=../domain/sub/schemas.yaml.PathsProcessor.processPaths->updateRefs(resolvedPath, pathRef)->updateRefs(Schema)->computePreprocessedRefresolves that result again against../domain/sub/paths.yamland gets../domain/domain/sub/schemas.yaml.
computePreprocessedRef skips only refs that do not start with a dot or that start with ./. A rebased ref does not start with ../ when the root document sits at the top, above every file it references, and for a path item one directory down the second resolution happens to be a no-op. So the existing tests from #2393 (issue-1948, issue-2066, issue-2393-regression) do not catch this.
2.1.47 rebased twice as well, but its computeRelativeRef concatenated without normalizing (../domain/sub/../domain/sub/schemas.yaml). The .. fallback in RefUtils.readExternalRef happened to recover that path. #2393 normalizes the second resolution, and the fallback can no longer recover it.
A fix with a regression test follows in a PR.
Checklist
- I have searched the existing issues and this is not a duplicate.
- I have provided sufficient information for maintainers to reproduce the issue.
Activity