{"record":{"id":"d1bdeabccf336ac2","repo":"apache/cassandra","slug":"invalid-value-for-the-paging-state","errorCode":null,"errorMessage":"Invalid value for the paging state","messagePattern":"Invalid value for the paging state","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/pager/PagingState.java","lineNumber":127,"sourceCode":"             * lengths and allocate huge byte arrays for readWithVIntLength() or,\n             * to a lesser extent, readWithShortLength()\n             */\n\n            if (protocolVersion.isGreaterThan(ProtocolVersion.V3))\n            {\n                if (isModernSerialized(bytes)) return modernDeserialize(bytes, protocolVersion);\n                if (isLegacySerialized(bytes)) return legacyDeserialize(bytes, ProtocolVersion.V3);\n            }\n\n            if (protocolVersion.isSmallerThan(ProtocolVersion.V4))\n            {\n                if (isLegacySerialized(bytes)) return legacyDeserialize(bytes, protocolVersion);\n                if (isModernSerialized(bytes)) return modernDeserialize(bytes, ProtocolVersion.V4);\n            }\n        }\n        catch (IOException e)\n        {\n            throw new ProtocolException(\"Invalid value for the paging state\");\n        }\n\n        throw new ProtocolException(\"Invalid value for the paging state\");\n    }\n\n    /*\n     * Modern serde (> VERSION_3)\n     */\n\n    private ByteBuffer modernSerialize() throws IOException\n    {\n        DataOutputBuffer out = new DataOutputBufferFixed(modernSerializedSize());\n        writeWithVIntLength(null == partitionKey ? EMPTY_BYTE_BUFFER : partitionKey, out);\n        writeWithVIntLength(null == rowMark ? EMPTY_BYTE_BUFFER : rowMark.mark, out);\n        out.writeUnsignedVInt32(remaining);\n        out.writeUnsignedVInt32(remainingInPartition);\n        return out.buffer(false);\n    }","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/pager/PagingState.java#L109-L145","documentation":"PagingState is the opaque cursor a client sends back to continue a paged query. deserialize() parses it for the requested protocol version; if the bytes cannot be decoded (malformed, truncated, wrong content) an IOException is caught and rethrown as this ProtocolException. The client sent a paging state the server cannot interpret.","triggerScenarios":"Sending a paging state byte string that fails both legacy and modern format detection/parsing for the given protocol version — corrupted cursor, bytes from a different cluster/table, manually crafted paging state, or paging state fetched with a protocol version the driver downgrades/mangles.","commonSituations":"Driver bug or downgraded protocol version serializing v5+ paging state incorrectly; copying paging state between different queries/tables; storing and re-sending a truncated cursor (e.g. in a URL or cache that altered bytes); mixing driver/server versions during upgrades.","solutions":["Discard the invalid paging state and restart pagination from the first page (execute the query without setPagingState)","Ensure driver protocol version matches the server's (v4/v5) and the driver is up to date; do not let the driver auto-downgrade","Never modify, truncate, or base64-transcode the paging state bytes; store them opaquely and byte-exact","Only reuse a paging state with the exact same query (same table, bound values, ordering) that produced it"],"exampleFix":"// before: reusing an old/corrupt cursor blindly\nstatement.setPagingState(storedBytes);\n// after: fall back to first page on ProtocolException\ntry {\n    statement.setPagingState(storedBytes);\n} catch (ProtocolException e) {\n    statement = statement.unsetPagingState(); // restart pagination\n}","handlingStrategy":"fallback","validationCode":"boolean validPagingState(byte[] ps) { return ps != null && ps.length > 0; }\n// only attach if produced by this exact query's previous page","typeGuard":"boolean isOpaqueCursor(Object o) { return o instanceof byte[] && ((byte[]) o).length > 0; }","tryCatchPattern":"try { stmt.setPagingState(cursor); return session.execute(stmt); }\ncatch (ProtocolException e) { return session.execute(stmt.unsetPagingState()); // restart from page 1 }","preventionTips":["Treat paging state as fully opaque bytes; never parse/transcode them","Only reuse a cursor with the identical query that produced it","Keep driver and protocol versions aligned with the server"],"tags":["protocol","paging","deserialization","client-request"],"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"}