Skip to content

[Bug]: 2.1.48 rebases a relative $ref inside an external path item twice when the root document is in a subdirectory #2418

Open

Description

@ericschlarmann

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

  1. 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
  2. Parse api/openapi.yaml with ParseOptions.setResolve(true) (new OpenAPIParser().readLocation(...) or OpenAPIV3Parser).

  3. Look at the request body schema $ref and 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:

  1. ExternalRefProcessor.processRefToExternalPathItem -> processPathItem -> processRefSchemaObject -> processRef rewrites it relative to the root document: join("../domain/sub/paths.yaml", "../../domain/sub/schemas.yaml") = ../domain/sub/schemas.yaml.
  2. PathsProcessor.processPaths -> updateRefs(resolvedPath, pathRef) -> updateRefs(Schema) -> computePreprocessedRef resolves that result again against ../domain/sub/paths.yaml and 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions