{"record":{"id":"0a637c6c89155ff1","repo":"apache/cassandra","slug":"the-data-cannot-be-deserialized-as-a-map","errorCode":null,"errorMessage":"The data cannot be deserialized as a map","messagePattern":"The data cannot be deserialized as a map","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/serializers/MapSerializer.java","lineNumber":130,"sourceCode":"            if (!accessor.isEmptyFromOffset(input, offset))\n                throw new MarshalException(\"Unexpected extraneous bytes after map value\");\n        }\n        catch (BufferUnderflowException | IndexOutOfBoundsException e)\n        {\n            throw new MarshalException(\"Not enough bytes to read a map\");\n        }\n    }\n\n    @Override\n    public <I> Map<K, V> deserialize(I input, ValueAccessor<I> accessor)\n    {\n        try\n        {\n            int n = readCollectionSize(input, accessor);\n            int offset = sizeOfCollectionSize();\n\n            if (n < 0)\n                throw new MarshalException(\"The data cannot be deserialized as a map\");\n\n            // If the received bytes are not corresponding to a map, n might be a huge number.\n            // In such a case we do not want to initialize the map with that initialCapacity as it can result\n            // in an OOM when put is called (see CASSANDRA-12618). On the other hand we do not want to have to resize\n            // the map if we can avoid it, so we put a reasonable limit on the initialCapacity.\n            Map<K, V> m = new LinkedHashMap<>(Math.min(n, 256));\n            for (int i = 0; i < n; i++)\n            {\n                I key = readNonNullValue(input, accessor, offset);\n                offset += sizeOfValue(key, accessor);\n                keys.validate(key, accessor);\n\n                I value = readNonNullValue(input, accessor, offset);\n                offset += sizeOfValue(value, accessor);\n                values.validate(value, accessor);\n\n                m.put(keys.deserialize(key, accessor), values.deserialize(value, accessor));\n            }","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/serializers/MapSerializer.java#L112-L148","documentation":"MapSerializer.deserialize reads the leading element count; if it is negative the bytes cannot possibly be a valid map, so this MarshalException is thrown explicitly. A negative count means the first 4 bytes were never a collection size — the data is either corrupt or produced by a different serializer.","triggerScenarios":"Deserializing a buffer whose first 4 bytes, read as a signed int, are negative — e.g. arbitrary bytes (text, blob) passed to a map serializer, or bit-flipped/corrupted stored cells.","commonSituations":"Schema mismatches where a column changed type but old data remains, reading through the wrong AbstractType, manual byte manipulation, disk corruption.","solutions":["Confirm the column's actual type matches the serializer used (check system_schema.tables).","If the schema changed, migrate or rewrite old rows so values match the new type.","Catch MarshalException and treat the row value as corrupt; use repair/scrub to fix stored data.","Validate before deserialize (mapType.validate) to catch bad input early with clearer context."],"exampleFix":"// before\nMap<K,V> m = mapSerializer.deserialize(randomBytes, accessor);\n// after\ntry {\n    mapType.validate(randomBytes);\n    Map<K,V> m = mapSerializer.deserialize(randomBytes, accessor);\n} catch (MarshalException e) {\n    throw new InvalidRequestException(\"Value is not a valid map: \" + e.getMessage());\n}","handlingStrategy":"validation","validationCode":"// Java\nif (bytes != null && bytes.remaining() >= 4) {\n    int n = bytes.getInt(bytes.position());\n    if (n < 0) throw new InvalidRequestException(\"first 4 bytes are not a map count\");\n}\nmapType.validate(bytes);","typeGuard":"boolean looksLikeMapBytes(ByteBuffer b) { return b != null && b.remaining() >= 4 && b.getInt(b.position()) >= 0; }","tryCatchPattern":"try { return mapSerializer.deserialize(bytes, accessor); } catch (MarshalException e) { throw new InvalidRequestException(\"Cannot deserialize as map: \" + e.getMessage()); }","preventionTips":["Check system_schema for column type changes when old data fails to deserialize.","Rewrite rows after schema type migrations so values match the new type.","Validate bytes with the intended type before structural deserialization."],"tags":["serialization","data-corruption","schema-mismatch"],"backgroundTag":"invalid-argument-format","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}