{"record":{"id":"194408e92b7bf5a5","repo":"apache/cassandra","slug":"null-deserialized-value-for-s-with-s","errorCode":null,"errorMessage":"'null' deserialized value for %s with %s","messagePattern":"'null' deserialized value for (.+?) with (.+?)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/sai/analyzer/NonTokenizingAnalyzer.java","lineNumber":78,"sourceCode":"        this.filterPipeline = getFilterPipeline();\n    }\n\n    @Override\n    public boolean hasNext()\n    {\n        // check that we know how to handle the input, otherwise bail\n        if (!indexTermType.isString())\n            return false;\n\n        if (hasNext)\n        {\n            try\n            {\n                String input = indexTermType.asString(this.input);\n\n                if (input == null)\n                {\n                    throw new MarshalException(String.format(\"'null' deserialized value for %s with %s\",\n                                                             ByteBufferUtil.bytesToHex(this.input), indexTermType));\n                }\n\n                String result = FilterPipelineExecutor.execute(filterPipeline, input);\n                \n                if (result == null)\n                {\n                    nextLiteral = null;\n                    next = null;\n                    return false;\n                }\n\n                nextLiteral = result;\n                next = indexTermType.fromString(result);\n\n                return true;\n            }\n            catch (MarshalException e)","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/sai/analyzer/NonTokenizingAnalyzer.java#L60-L96","documentation":"NonTokenizingAnalyzer.hasNext deserializes the indexed term via indexTermType.asString(input). If the deserialized string is null for a non-null input byte buffer, the analyzer treats it as an internal marshalling inconsistency and throws MarshalException reporting the hex bytes and the term type. This indicates the term bytes do not match the expected type encoding.","triggerScenarios":"Indexing/querying where the term ByteBuffer for the index term type cannot be deserialized to a String (null result) — typically corrupt or type-mismatched term bytes fed into the analyzer during index build or query validation.","commonSituations":"Schema/type changes under an existing SAI index (column type altered without rebuilding the index); reading SSTables/index files written by an incompatible version; internal corruption.","solutions":["Rebuild the affected SAI index (DROP and re-CREATE) so all terms are re-encoded with the current type.","Verify the column type has not changed since the index was created; if it has, recreate the index.","Run repairs/scrub and check for corrupted SSTables or index files.","If reproducible after rebuild, capture the type/hex in the message and file a Cassandra bug with the version."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (MarshalException e) { if (e.getMessage().startsWith(\"'null' deserialized value\")) { // rebuild the SAI index for this table; do not retry the same operation blindly } else throw e; }","preventionTips":["Rebuild SAI indexes after altering column types","Keep index files and schema versions in sync across upgrades","Treat MarshalException on index paths as corruption: scrub/repair and rebuild"],"tags":["cassandra","sai","analyzer","marshal","corruption"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}