{"record":{"id":"06fe6c037634a0f0","repo":"apache/cassandra","slug":"the-data-cannot-be-deserialized-as-a-list","errorCode":null,"errorMessage":"The data cannot be deserialized as a list","messagePattern":"The data cannot be deserialized as a list","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/serializers/ListSerializer.java","lineNumber":103,"sourceCode":"            if (!accessor.isEmptyFromOffset(input, offset))\n                throw new MarshalException(\"Unexpected extraneous bytes after list value\");\n        }\n        catch (BufferUnderflowException | IndexOutOfBoundsException e)\n        {\n            throw new MarshalException(\"Not enough bytes to read a list\");\n        }\n    }\n\n    @Override\n    public <V> List<T> deserialize(V input, ValueAccessor<V> 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 list\");\n\n            // If the received bytes are not corresponding to a list, n might be a huge number.\n            // In such a case we do not want to initialize the list with that size as it can result\n            // in an OOM (see CASSANDRA-12618). On the other hand we do not want to have to resize the list\n            // if we can avoid it, so we put a reasonable limit on the initialCapacity.\n            List<T> l = new ArrayList<>(Math.min(n, 256));\n            for (int i = 0; i < n; i++)\n            {\n                // CASSANDRA-6839: \"We can have nulls in lists that are used for IN values\"\n                // CASSANDRA-8613 checks IN clauses and throws an exception if null is in the list.\n                // Leaving for this as-is for now in case there is some unknown use\n                // for it, but should likely be changed to readNonNull. Validate has been\n                // changed to throw on null elements as otherwise it would NPE, and it's unclear\n                // if callers could handle null elements.\n                V databb = readValue(input, accessor, offset);\n                offset += sizeOfValue(databb, accessor);\n                if (databb != null)\n                {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/serializers/ListSerializer.java#L85-L121","documentation":"ListSerializer.deserialize() reads a signed 32-bit element count from the head of the buffer; a negative count cannot represent a valid list, so this MarshalException is thrown. A negative count almost always indicates corrupted or mis-framed bytes (e.g. wrong offset, wrong endianness, or deserializing a non-list blob as a list).","triggerScenarios":"Calling ListSerializer.deserialize(input, accessor) where the first 4 bytes, interpreted as an int, are negative (high bit set) — e.g. deserializing a random blob, a map/set, or bytes with wrong endianness as a list.","commonSituations":"Casting a map or set blob to a list type; byte-order mismatch between writer and reader; reading stale SSTable data after a serialization format change; application bugs writing a raw int (e.g. -1 sentinel) where a list count belongs.","solutions":["Confirm the column/type is actually list (not map/set/frozen variant) and deserialize with the matching serializer.","Dump the first bytes (toHex) and verify the count header; fix writer endianness/count encoding if wrong.","Re-serialize the data from the source of truth; corrupted at-rest data needs a rewrite (repair/scrub or re-ETL).","Guard callers by validating with ListSerializer.validate() before deserialize to get an earlier, clearer failure."],"exampleFix":"// before\nList<Integer> l = ListSerializer.instance.deserialize(mysteryBlob, ByteBufferUtil.NONE);\n// after\nListSerializer.instance.validate(mysteryBlob, ByteBufferUtil.NONE); // throws descriptive MarshalException first\nList<Integer> l = ListSerializer.instance.deserialize(mysteryBlob, ByteBufferUtil.NONE);","handlingStrategy":"try-catch","validationCode":"int count = blob.getInt(blob.position()); if (count < 0) throw new MarshalException(\"negative list count: \" + count);","typeGuard":"boolean isPlausibleListBlob(java.nio.ByteBuffer b) { return b != null && b.remaining() >= 4 && b.getInt(b.position()) >= 0; }","tryCatchPattern":"try { return listSerializer.deserialize(blob, accessor); } catch (org.apache.cassandra.exceptions.MarshalException e) { log.error(\"cannot deserialize list: {}\", e.getMessage()); return Collections.emptyList(); }","preventionTips":["Verify the target type is actually a list before using ListSerializer","Check endianness/count encoding on the writer side","Call validate() before deserialize in ingestion paths"],"tags":["cassandra","serialization","collections","deserialization"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}