Skip to content

CatalogObject missing equals()/hashCode() breaks equality for all types containing nested CatalogObject #194

@ZoeyJones

Description

@ZoeyJones

Bug Description

CatalogObject (a Fern-generated discriminated union type) does not implement equals() or hashCode(), which means it falls back to reference identity comparison. This breaks equals() on any type that transitively contains CatalogObject.

Impact

CatalogModifierList has a field modifiers: Optional<List<CatalogObject>>. Its equals() method compares this field, which calls List.equals()CatalogObject.equals()reference comparison → always false for distinct instances with identical content.

This affects all types with recursive CatalogObject references, making their equals() unreliable despite being implemented.

Reproduction

CatalogObject a = ObjectMappers.JSON_MAPPER.readValue(json, CatalogObject.class);
CatalogObject b = ObjectMappers.JSON_MAPPER.readValue(json, CatalogObject.class);

// Fails — same content, different references
assert a.equals(b); // false

// Inner types also fail due to nested CatalogObject
CatalogObjectModifierList mlA = a.getModifierList().get();
CatalogObjectModifierList mlB = b.getModifierList().get();
assert mlA.equals(mlB); // false — because modifiers list contains CatalogObject

Error message from Truth:

expected: (non-equal instance of same class with same string representation)

Root Cause

The inner Value subtypes (e.g., ItemValue, ModifierListValue) do implement equals()/hashCode() (delegating to the unwrapped type), but the outer CatalogObject class does not delegate to its value field:

// CatalogObject.java — missing:
@Override
public boolean equals(Object other) {
    if (this == other) return true;
    return other instanceof CatalogObject && value.equals(((CatalogObject) other).value);
}

@Override
public int hashCode() {
    return Objects.hash(value);
}

Expected Behavior

CatalogObject should delegate equals()/hashCode() to its inner Value field, consistent with how all other generated types and the inner Value subtypes already implement equality.

Environment

  • SDK version: 46.0.0.20260122
  • Java version: 25

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions