{"record":{"id":"0e5154cf581907c0","repo":"spring-projects/spring-ai","slug":"cassandra-uses-a-custom-dovalue-columnmetadata-ob","errorCode":null,"errorMessage":"Cassandra uses a custom doValue(ColumnMetadata, Object, StringBuilder) implementation that leverages CodecRegistry.DEFAULT.codecFor(dataType).format(v). This method should not be called.","messagePattern":"Cassandra uses a custom doValue\\(ColumnMetadata, Object, StringBuilder\\) implementation that leverages CodecRegistry\\.DEFAULT\\.codecFor\\(dataType\\)\\.format\\(v\\)\\. This method should not be called\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraFilterExpressionConverter.java","lineNumber":166,"sourceCode":"\t\t\t\tname = name.substring(1, name.length() - 1);\n\t\t\t\tcolumn = Optional.ofNullable(this.columnsByName.get(name));\n\t\t\t}\n\t\t}\n\t\treturn column;\n\t}\n\n\t/**\n\t * Cassandra uses a custom value formatting approach via\n\t * {@link #doValue(ColumnMetadata, Object, StringBuilder)} that leverages the driver's\n\t * CodecRegistry. This method is not used in the normal flow and will throw an\n\t * exception if called.\n\t * @param value the value to convert\n\t * @param context the context to append the string representation to\n\t * @throws UnsupportedOperationException always, as this method should not be called\n\t */\n\t@Override\n\tprotected void doSingleValue(Object value, StringBuilder context) {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Cassandra uses a custom doValue(ColumnMetadata, Object, StringBuilder) implementation \"\n\t\t\t\t\t\t+ \"that leverages CodecRegistry.DEFAULT.codecFor(dataType).format(v). \"\n\t\t\t\t\t\t+ \"This method should not be called.\");\n\t}\n\n}\n","sourceCodeStart":148,"sourceCodeEnd":173,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraFilterExpressionConverter.java#L148-L173","documentation":"CassandraFilterExpressionConverter overrides doValue(ColumnMetadata, Object, StringBuilder) and formats values via CodecRegistry codecs based on the column's CQL data type. The generic doSingleValue hook is therefore intentionally disabled and always throws UnsupportedOperationException to catch incorrect dispatch paths.","triggerScenarios":"A code path or subclass (or framework upgrade changing FilterVectorExpressionConverter internals) that invokes doSingleValue directly instead of the Cassandra-specific doValue overload; custom subclasses that bypass the Cassandra column-aware conversion.","commonSituations":"Upgrading Spring AI where the base class converter starts calling doSingleValue for some expression types; writing a custom converter subclass that reuses doSingleValue.","solutions":["Ensure values are converted through doValue(ColumnMetadata, Object, StringBuilder), which uses CodecRegistry.DEFAULT.codecFor(dataType).format(v).","If extending the converter, override doValue instead of calling doSingleValue.","If this fires from library internals after an upgrade, pin to a compatible Spring AI version or file an issue."],"exampleFix":"// before (custom subclass calling the generic hook)\nprotected void doValue(Object v, StringBuilder ctx) { doSingleValue(v, ctx); }\n// after\nprotected void doValue(ColumnMetadata col, Object v, StringBuilder ctx) {\n  ctx.append(CodecRegistry.DEFAULT.codecFor(col.getType()).format(v));\n}","handlingStrategy":"type-guard","validationCode":"// Ensure the store/converter in use is CassandraFilterExpressionConverter, not the base class\nif (!(converter instanceof CassandraFilterExpressionConverter c)) {\n  throw new IllegalStateException(\"Cassandra store requires its own filter converter\");\n}","typeGuard":"boolean usesCassandraConverter(FilterVectorExpressionConverter c) {\n  return c instanceof CassandraFilterExpressionConverter;\n}","tryCatchPattern":"try {\n  converter.convertExpression(filter);\n} catch (UnsupportedOperationException e) {\n  throw new IllegalStateException(\"Converter must use Cassandra doValue(ColumnMetadata,...) path\", e);\n}","preventionTips":["Do not subclass CassandraFilterExpressionConverter and override doSingleValue.","After Spring AI upgrades, run integration tests covering all filter operators against Cassandra.","Keep value formatting inside doValue(ColumnMetadata, Object, StringBuilder) where codec info is available."],"tags":["cassandra","filter-expression","unsupported-operation","codec"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}