Skip to content

[Bug]: swagger-annotations 2.2.45 still emits spurious additionalProperties/contains/unevaluatedItems with "##default" sentinel on response schemas #5090

@thejeff77

Description

@thejeff77

Description

After upgrading from swagger-annotations 2.2.43 to 2.2.45, the generated OpenAPI 3.1.0 spec contains spurious JSON Schema keywords (additionalProperties, contains, unevaluatedItems, items) with "default": "##default" sentinel values on response schemas where they do not belong. This is related to the sentinel change in #5063 (v2.2.44) and the partial fix in #5078 (v2.2.45), but v2.2.45 does not fully resolve the issue.

This is distinct from #5086 (which covers @Parameter + @ArraySchema). This bug affects response body schemas — both $ref schemas and type: array schemas.

Environment

  • Spring Boot: 3.5.11
  • springdoc-openapi: 2.8.16
  • swagger-annotations: 2.2.45 (regression confirmed absent in 2.2.43)
  • OpenAPI version: 3.1.0

Reproduction

A standard Spring Boot controller returning a List<T>:

@GetMapping("/v1/items/{item-id}/details")
public ResponseEntity<List<ItemDetailResponse>> getDetails(
    @PathVariable("item-id") String itemId) {
    // ...
}

With swagger-annotations 2.2.43, the generated schema for the 200 response is:

{
  "type": "array",
  "items": {
    "$ref": "#/components/schemas/ItemDetailResponse"
  }
}

With swagger-annotations 2.2.45, the same endpoint produces:

{
  "type": "array",
  "additionalProperties": {
    "default": "##default"
  },
  "contains": {
    "default": "##default"
  },
  "items": {
    "$ref": "#/components/schemas/ItemDetailResponse",
    "contains": {
      "default": "##default"
    },
    "default": "##default",
    "unevaluatedItems": {
      "default": "##default"
    }
  },
  "unevaluatedItems": {
    "default": "##default"
  }
}

Similarly, endpoints returning a single object via $ref gain extraneous keywords:

{
  "$ref": "#/components/schemas/SomeResponse",
  "additionalProperties": {
    "default": "##default"
  },
  "contains": {
    "default": "##default"
  },
  "default": "##default",
  "items": {
    "default": "##default"
  },
  "unevaluatedItems": {
    "default": "##default"
  }
}

Scale of impact

In our production spec (~250 endpoint Spring Boot service), upgrading to 2.2.45 introduces:

Keyword Spurious occurrences with ##default
default 1,375
contains 246
unevaluatedItems 246
additionalProperties 242
items 241

Why this breaks downstream tools

The combination of type: array + additionalProperties is semantically invalid — additionalProperties is an object-only keyword. Code generators like Fabrikt interpret additionalProperties as a signal that the schema represents a map/dictionary. When combined with type: array, this creates an impossible type (array + MAP specialization), causing a crash:

java.lang.IllegalStateException: Unknown OAS type: array and format: null 
  and specialization: MAP

Root cause hypothesis

The ##default sentinel introduced in #5063 is not being filtered out in all code paths before schema serialization. PR #5078 addressed the defaultValue merge logic, but the sentinel is still leaking through the sub-schema keywords (additionalProperties, contains, unevaluatedItems, items) that get populated with { "default": "##default" } objects when they should not be present at all.

Expected behavior

Response schemas should not contain any ##default sentinel values or spurious sub-schema keywords that were not explicitly defined in the source annotations. The output with 2.2.45 should match the clean output from 2.2.43.

Workaround

Pin swagger-annotations to 2.2.43.

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