apache/cassandra · error · MarshalException
Expected a UTF-8 string, but got a %s: %s
Error message
Expected a UTF-8 string, but got a %s: %s
What it means
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.
Source
Thrown at src/java/org/apache/cassandra/db/marshal/UTF8Type.java:59
private static final ByteBuffer MASKED_VALUE = instance.decompose("****");
UTF8Type() {super(ComparisonType.BYTE_ORDER);} // singleton
public ByteBuffer fromString(String source)
{
return decompose(source);
}
@Override
public Term fromJSONObject(Object parsed) throws MarshalException
{
try
{
return new Constants.Value(fromString((String) parsed));
}
catch (ClassCastException exc)
{
throw new MarshalException(String.format(
"Expected a UTF-8 string, but got a %s: %s", parsed.getClass().getSimpleName(), parsed));
}
}
@Override
public String toJSONString(ByteBuffer buffer, ProtocolVersion protocolVersion)
{
try
{
return '"' + JsonUtils.quoteAsJsonString(ByteBufferUtil.string(buffer, StandardCharsets.UTF_8)) + '"';
}
catch (CharacterCodingException exc)
{
throw new AssertionError("UTF-8 value contained non-utf8 characters: ", exc);
}
}
@OverrideView on GitHub (pinned to 88fd0f6a0e)
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
Example fix
// before Object parsed = JSONValue.parse(raw); // 42 -> Long term = utf8Type.fromJSONObject(parsed); // MarshalException // after if (!(parsed instanceof String)) parsed = String.valueOf(parsed); term = utf8Type.fromJSONObject(parsed);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(parsed instanceof String)) throw new IllegalArgumentException("UTF8 value must be a JSON string, got: " + parsed); Type guard
function isString(v) { return typeof v === 'string'; } // Java: if (!(parsed instanceof String)) ... Try / catch
try { term = utf8Type.fromJSONObject(parsed); } catch (MarshalException e) { /* coerce with String.valueOf(parsed) and retry */ } Prevention
- Always serialize text columns as quoted JSON strings
- Validate payload types against the schema before binding
- Use String.valueOf coercion at the API boundary
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Expected a float value, but got a %s: %s
- Expected an ascii string, but got a %s: %s
- Expected a double value, but got a %s: %s
- Expected an empty string, but got: %s
- Expected a string representation of an inet value, but got a
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/56acbdd0bb6d13c0.
Report an issue: GitHub.