Skip to content

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

Description

@plantexchen

[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:

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:

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)

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions