swagger-api / swagger-api/swagger-core
[Bug]: @Nullable property mutates shared enumAsRef component schema in OpenAPI 3.1
Nobody has claimed this yet.
- 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
@Nullableannotations 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
@Nullabledoes 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 goodswagger-core-2.2.44-schema-reproducer.json— first affected
The relevant difference is:
"StatusType": {
- "type": "string",
+ "type": [
+ "string",
+ "null"
+ ],
"enum": [...]
}
Steps to reproduce
-
Download and extract the attached reproducer.
-
Run:
mvn clean spring-boot:run
- Open:
http://localhost:8080/v3/api-docs
- Inspect:
components.schemas.StatusType
- With
swagger-core-jakarta2.2.44, the generated component contains:
"type": ["string", "null"]
- Change only the Maven property:
<swagger-core.version>2.2.43</swagger-core.version>
- 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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