quarkusio/quarkus · error · ClassCastException

Cannot cast <item> of kind <kind> to a io.quarkus.redis.data

Error message

Cannot cast <item> of kind <kind> to a io.quarkus.redis.datasource.graph.GraphQueryResponseItem$NodeItem

What it means

GraphQueryResponseItem results are tagged with a Kind (SCALAR, NODE, RELATION). asNodeItem() throws a ClassCastException when invoked on an item that is not a NODE, guarding the unsafe downcast to NodeItem. Use kind() to determine the correct accessor before casting.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/graph/GraphQueryResponseItem.java:28

        RELATION
    }

    Kind kind();

    String name();

    default ScalarItem asScalarItem() {
        if (this instanceof ScalarItem) {
            return (ScalarItem) this;
        }
        throw new ClassCastException("Cannot cast " + this + " of kind " + kind() + " to a " + ScalarItem.class.getName());
    }

    default NodeItem asNodeItem() {
        if (this instanceof NodeItem) {
            return (NodeItem) this;
        }
        throw new ClassCastException("Cannot cast " + this + " of kind " + kind() + " to a " + NodeItem.class.getName());
    }

    default RelationItem asRelationItem() {
        if (this instanceof RelationItem) {
            return (RelationItem) this;
        }
        throw new ClassCastException("Cannot cast " + this + " of kind " + kind() + " to a " + RelationItem.class.getName());
    }

    interface ScalarItem extends GraphQueryResponseItem {

        boolean asBoolean();

        int asInteger();

        double asDouble();

        boolean isNull();

View on GitHub (pinned to e1c734241f)

Solutions

  1. Check item.kind() == Kind.NODE before calling asNodeItem()
  2. Dispatch on kind() to pick asScalarItem/asNodeItem/asRelationItem
  3. Align the Cypher RETURN clause so the parsed column is actually a node
  4. Wrap the call in try-catch for ClassCastException if shape cannot be predicted

Example fix

// before
NodeItem n = row.get(0).asNodeItem();
// after
GraphQueryResponseItem item = row.get(0);
NodeItem n = item instanceof GraphQueryResponseItem.NodeItem
    ? item.asNodeItem()
    : null; // handle non-node items explicitly
Defensive patterns

Strategy: type-guard

Validate before calling

if (item.kind() != GraphQueryResponseItem.Kind.NODE) {
    throw new IllegalStateException("Expected NODE but got " + item.kind());
}

Type guard

boolean isNode(GraphQueryResponseItem item) {
    return item instanceof GraphQueryResponseItem.NodeItem;
}

Try / catch

try {
    NodeItem n = item.asNodeItem();
} catch (ClassCastException e) {
    // handle SCALAR/RELATION items instead
}

Prevention

When it happens

Trigger: Calling item.asNodeItem() on an item whose kind() is SCALAR or RELATION — e.g. iterating 'RETURN label, node' rows where the first column is a scalar label, or assuming a MATCH returns nodes when a projection actually returns properties.

Common situations: Query returns mixed node/scalar columns; Cypher query was refactored to RETURN n.property instead of n; loop treats all graph results as nodes.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/727a5beb33a7d253. Report an issue: GitHub.