apache/cassandra · warning · IllegalStateException

Key already maps to value

Error message

Key ${key} already maps to value ${previousValue}

What it means

ByteBufferUtil.objectToBytes converts UDT/collection field objects (Map, Set, Date, etc.) into ByteBuffers for decomposition. When a Map contains two keys that serialize to the same ByteBuffer, the duplicate insertion is detected and IllegalStateException is thrown.

Solutions

  1. Deduplicate map keys before conversion so each key serializes uniquely
  2. Ensure key objects are of a consistent type
  3. Review custom serializers for keys to avoid producing identical byte output
  4. Validate input maps before constructing UDTs

Example fix

// before
Map<Object, Object> m = new HashMap<>();
m.put(1, "a"); m.put(1L, "b"); // both -> same bytes
// after
m.put(1L, "b"); // one canonical key type only
Defensive patterns

Strategy: validation

Validate before calling

// detect byte-colliding keys before conversion
Set<ByteBuffer> seen = new HashSet<>();
for (Object k : map.keySet()) {
    if (!seen.add(ByteBufferUtil.objectToBytes(k).duplicate()))
        throw new IllegalArgumentException("duplicate serialized key: " + k);
}

Prevention

When it happens

Trigger: Calling objectToBytes on a Map with keys that are equal after conversion (e.g., distinct objects whose byte representations collide), typically via UDT serialization of a map value.

Common situations: Building a UDT value in application code with keys differing in Java type but equal bytes (e.g., 1 as Integer vs 1L as Long both becoming the same buffer); custom serializers producing identical bytes for different keys.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/87c7c8f89a8be236. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/ByteBufferUtil.java:642

        else if (obj instanceof List)
        {
            List<?> list = (List<?>) obj;
            // convert subtypes to BB
            List<ByteBuffer> bbs = list.stream().map(ByteBufferUtil::objectToBytes).collect(Collectors.toList());
            // decompose/serializer doesn't use the isMultiCell, so safe to do this
            return ListType.getInstance(BytesType.instance, false).decompose(bbs);
        }
        else if (obj instanceof Map)
        {
            Map<?, ?> map = (Map<?, ?>) obj;
            // convert subtypes to BB
            Map<ByteBuffer, ByteBuffer> bbs = new LinkedHashMap<>();
            for (Map.Entry<?, ?> e : map.entrySet())
            {
                Object key = e.getKey();
                ByteBuffer previousValue = bbs.put(objectToBytes(key), objectToBytes(e.getValue()));
                if (previousValue != null)
                    throw new IllegalStateException("Key " + key + " already maps to value " + previousValue);
            }
            // decompose/serializer doesn't use the isMultiCell, so safe to do this
            return MapType.getInstance(BytesType.instance, BytesType.instance, false).decompose(bbs);
        }
        else if (obj instanceof Set)
        {
            Set<?> set = (Set<?>) obj;
            // convert subtypes to BB
            Set<ByteBuffer> bbs = new LinkedHashSet<>();
            for (Object o : set)
                if (!bbs.add(objectToBytes(o)))
                    throw new IllegalStateException("Object " + o + " maps to a buffer that already exists in the set");
            // decompose/serializer doesn't use the isMultiCell, so safe to do this
            return SetType.getInstance(BytesType.instance, false).decompose(bbs);
        }
        else if (obj instanceof Date)
            return TimestampType.instance.decompose((Date) obj);
        else

View on GitHub (pinned to 88fd0f6a0e)