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);
        }
    }

    @Override

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Quote the value so it parses as a JSON string before calling fromJSONObject
  2. String.valueOf(...) the value in application code before handing it to the type
  3. 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

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/56acbdd0bb6d13c0. Report an issue: GitHub.