{"record":{"id":"56acbdd0bb6d13c0","repo":"apache/cassandra","slug":"expected-a-utf-8-string-but-got-a-s-s","errorCode":null,"errorMessage":"Expected a UTF-8 string, but got a %s: %s","messagePattern":"Expected a UTF-8 string, but got a (.+?): (.+?)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/UTF8Type.java","lineNumber":59,"sourceCode":"    private static final ByteBuffer MASKED_VALUE = instance.decompose(\"****\");\n\n    UTF8Type() {super(ComparisonType.BYTE_ORDER);} // singleton\n\n    public ByteBuffer fromString(String source)\n    {\n        return decompose(source);\n    }\n\n    @Override\n    public Term fromJSONObject(Object parsed) throws MarshalException\n    {\n        try\n        {\n            return new Constants.Value(fromString((String) parsed));\n        }\n        catch (ClassCastException exc)\n        {\n            throw new MarshalException(String.format(\n                    \"Expected a UTF-8 string, but got a %s: %s\", parsed.getClass().getSimpleName(), parsed));\n        }\n    }\n\n    @Override\n    public String toJSONString(ByteBuffer buffer, ProtocolVersion protocolVersion)\n    {\n        try\n        {\n            return '\"' + JsonUtils.quoteAsJsonString(ByteBufferUtil.string(buffer, StandardCharsets.UTF_8)) + '\"';\n        }\n        catch (CharacterCodingException exc)\n        {\n            throw new AssertionError(\"UTF-8 value contained non-utf8 characters: \", exc);\n        }\n    }\n\n    @Override","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/UTF8Type.java#L41-L77","documentation":"UTF8Type.fromJSONObject only accepts JSON values that are strings; anything else (number, boolean, map, list) cannot be converted to a UTF-8 column value. The cast to (String) throws ClassCastException, which is translated into this MarshalException naming the actual runtime type and value received.","triggerScenarios":"Calling fromJSONObject with a parsed JSON object that is not a String, e.g. passing Json.parse(\"123\") (an Integer/Double), a Boolean, or a Map/List into UTF8Type.instance.fromJSONObject.","commonSituations":"CQL literal passed as bare number or boolean for a text/varchar column (e.g. INSERT ... VALUES (42) instead of '42'); JSON payload where a field arrives as a number/bool but the column is text; client drivers serializing unquoted scalars.","solutions":["Quote the value so it parses as a JSON string before calling fromJSONObject","String.valueOf(...) the value in application code before handing it to the type","Verify the target column type; if the column should hold numbers, use Int32Type/LongType instead of UTF8Type"],"exampleFix":"// before\nObject parsed = JSONValue.parse(raw); // 42 -> Long\nterm = utf8Type.fromJSONObject(parsed); // MarshalException\n// after\nif (!(parsed instanceof String)) parsed = String.valueOf(parsed);\nterm = utf8Type.fromJSONObject(parsed);","handlingStrategy":"type-guard","validationCode":"if (!(parsed instanceof String)) throw new IllegalArgumentException(\"UTF8 value must be a JSON string, got: \" + parsed);","typeGuard":"function isString(v) { return typeof v === 'string'; } // Java: if (!(parsed instanceof String)) ...","tryCatchPattern":"try { term = utf8Type.fromJSONObject(parsed); } catch (MarshalException e) { /* coerce with String.valueOf(parsed) and retry */ }","preventionTips":["Always serialize text columns as quoted JSON strings","Validate payload types against the schema before binding","Use String.valueOf coercion at the API boundary"],"tags":["cassandra","marshalling","json","type-mismatch"],"backgroundTag":"type-mismatch","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"}