Skip to content

[Bug]: ModelResolver cycle guard drops items from recursive List<T> schemas (regression since 2.2.41) #5187

Description

@janf291

Description

PR #5004 added a cycle guard (typesBeingResolved, resolveArraySchemaWithCycleGuard) to prevent StackOverflowError on recursive models. When the guard triggers, AnnotationsUtils.getArraySchema(...) is invoked with processSchemaImplementation = false and the setItems(...)
branch is skipped:

if (arraySchema.schema() != null) {
    if (arraySchema.schema().implementation().equals(Void.class)) {
        // setItems called
    } else if (processSchemaImplementation) {
        // setItems called
    }
    // else: items is never set
}

The resulting schema is missing its items (and degrades to type: object); in deeper cycles the property is dropped from the schema entirely. The referenced type is already registered in the ModelConverterContext at that point, so a $ref could safely be emitted.

Swagger-core version

  • Broken: 2.2.412.2.49 (verified against master)
  • Last working: 2.2.40

How to reproduce

class A { B b; }
class B { List<A> children; }

var schemas = ModelConverters.getInstance().readAll(B.class);
System.out.println(Json.pretty(schemas.get("B")));

Expected (≤ 2.2.40):

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

Actual (≥ 2.2.41):

"children": { "type": "object" }

Suggested fix

When the guard prevents setItems, fall back to a $ref to the item type already registered in the ModelConverterContext, instead of leaving items unset. This preserves the StackOverflow fix from #5004 while emitting a valid schema.

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions