swagger-api / swagger-api/swagger-core

[Bug]: @Nullable property mutates shared enumAsRef component schema in OpenAPI 3.1

Open
#5,310 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
Dominant language
Java
Stars
7.5k
Forks
2.3k
Avg merge
18h 1m
Merged PRs (30d)
10

Description

[Bug]: @Nullable property mutates shared enumAsRef component schema in OpenAPI 3.1

Description

When an enum annotated with @Schema(enumAsRef = true) is referenced from both a nullable and a non-nullable property, processing the @Nullable property makes the shared enum component schema nullable globally.

This means that other references to the same enum are also effectively nullable, even if the corresponding property is explicitly annotated with @NotNull.

The issue is reproducible with OpenAPI 3.1 and appears to be a regression introduced in swagger-core 2.2.44.

Minimal example

Shared enum:

@Schema(enumAsRef = true)
public enum StatusType {
    NOT_REQUESTED,
    REQUESTED,
    APPROVED,
    REJECTED
}

Nullable request property:

public class VehicleUpdateRequestDto {

    @Nullable
    @Schema(
        description = "New status.",
        requiredMode = Schema.RequiredMode.NOT_REQUIRED
    )
    private StatusType status;
}

Non-null response property:

public class VehicleResponseDto {

    @NotNull
    @Schema(
        description = "Current status.",
        defaultValue = "NOT_REQUESTED"
    )
    private StatusType status;
}

Both properties reference the same component schema because of enumAsRef = true.

Actual behavior

With swagger-core 2.2.44:

"StatusType": {
  "type": [
    "string",
    "null"
  ],
  "enum": [
    "NOT_REQUESTED",
    "REQUESTED",
    "APPROVED",
    "REJECTED"
  ]
}

The response property is nevertheless correctly listed as required:

"VehicleResponseDto": {
  "type": "object",
  "properties": {
    "status": {
      "$ref": "#/components/schemas/StatusType",
      "default": "NOT_REQUESTED",
      "description": "Current status."
    }
  },
  "required": [
    "status"
  ]
}

The problem is that the referenced shared component itself now allows null.

Expected behavior

Property-level @Nullable should not mutate the shared enum component schema.

The shared component should remain:

"StatusType": {
  "type": "string",
  "enum": [
    "NOT_REQUESTED",
    "REQUESTED",
    "APPROVED",
    "REJECTED"
  ]
}

Nullability of the request property should be represented without changing the shared component schema used by other non-null references.

Regression

The behavior was reproduced with the same minimal application by changing only the swagger-core version:

swagger-core components.schemas.StatusType Result
2.2.41 "type": "string" OK
2.2.43 "type": "string" OK
2.2.44 "type": ["string", "null"] Affected
2.2.55 "type": ["string", "null"] Still affected
  • Last known good version: 2.2.43
  • First known affected version: 2.2.44
  • Still reproducible with: 2.2.55

Possible relation to existing issues

This regression coincides with the introduction of native @Nullable support for OpenAPI 3.1 in:

  • #5001
  • #5018 — Add support for @Nullable annotations in OpenAPI 3.1 schemas

In #5018, nullable properties started adding "null" to the schema type set for OpenAPI 3.1.

A similar shared-schema mutation was subsequently reported for object schemas and addressed by:

  • #5077
  • #5115
  • #5124 — fix: ensure that @Nullable does not incorrectly affect object schemas

This issue appears to be the equivalent case for shared enum component schemas created with @Schema(enumAsRef = true).

Reproducer

A minimal Spring Boot reproducer is attached.

Environment:

  • Java 17
  • Spring Boot 3.5.16
  • SpringDoc 2.9.0
  • OpenAPI 3.1
  • swagger-core-jakarta 2.2.44

The attached OpenAPI outputs demonstrate the regression directly:

  • swagger-core-2.2.43-schema-reproducer.json — last known good
  • swagger-core-2.2.44-schema-reproducer.json — first affected

The relevant difference is:

"StatusType": {
-  "type": "string",
+  "type": [
+    "string",
+    "null"
+  ],
   "enum": [...]
}

Steps to reproduce

  1. Download and extract the attached reproducer.

  2. Run:

mvn clean spring-boot:run
  1. Open:
http://localhost:8080/v3/api-docs
  1. Inspect:
components.schemas.StatusType
  1. With swagger-core-jakarta 2.2.44, the generated component contains:
"type": ["string", "null"]
  1. Change only the Maven property:
<swagger-core.version>2.2.43</swagger-core.version>
  1. Restart the application and inspect the same component.

It now contains:

"type": "string"

The regression can therefore be reproduced by changing only swagger-core from 2.2.43 to 2.2.44.

Dependency verification

The resolved Swagger dependencies can be verified with:

mvn dependency:tree -Dincludes=io.swagger.core.v3

swagger-core-jakarta, swagger-annotations-jakarta, and swagger-models-jakarta should all resolve to the version being tested.

Attachments

Image [swagger-nullable-enum-shared-schema-reproducer.zip](https://github.com/user-attachments/files/31800759/swagger-nullable-enum-shared-schema-reproducer.zip) [swagger-core-2.2.43-schema-reproducer.json](https://github.com/user-attachments/files/31800757/swagger-core-2.2.43-schema-reproducer.json) [swagger-core-2.2.44-schema-reproducer.json](https://github.com/user-attachments/files/31800758/swagger-core-2.2.44-schema-reproducer.json)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attached Spring Boot reproducer and run mvn clean spring-boot:run, then inspect components.schemas.StatusType at /v3/api-docs under OpenAPI 3.1. Compare swagger-core-jakarta 2.2.43 and 2.2.44, and trace the schema generation behavior for @Schema(enumAsRef = true) with nullable and non-nullable properties. Done means the shared enum component stays non-null while the nullable property remains represented correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.