apache/cassandra · error · MarshalException

Expected a string, but got a

Error message

Expected a %s string, but got a %s: %s

What it means

PseudoUtf8Type.fromJSONObject expects a JSON string for this UTF8-like type (used for token/timestamp-as-string pseudo types; describe() names the expected kind). Non-string JSON values throw ClassCastException, rethrown as this MarshalException including the type description and offending value.

Solutions

  1. Wrap the value as a JSON string before sending (String.valueOf on the client).
  2. Add a client-side check that the field is a string before serializing the payload.
  3. Avoid writing null into these columns; omit the field or use a sentinel string per your data model.

Example fix

// before
{"token": 12345}
// after
{"token": "12345"}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(parsed instanceof String)) throw new IllegalArgumentException(describe() + " must be a string");

Type guard

boolean isUtf8String(Object v) { return v instanceof String; }

Try / catch

try { return type.fromJSONObject(parsed); } catch (MarshalException e) { /* handle non-string JSON */ }

Prevention

When it happens

Trigger: fromJson()/INSERT JSON where a column of a PseudoUtf8Type (e.g. token or timestamp-as-string) is given a number, boolean, null, array or object instead of a string.

Common situations: Generating JSON where the token value is numeric; nulling out the field when the source value is missing; client model uses a non-string type for these pseudo columns.

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/7cdb98396ae02904. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/PseudoUtf8Type.java:52

    PseudoUtf8Type() {super(ComparisonType.CUSTOM);} // singleton

    abstract String describe();

    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 %s string, but got a %s: %s", describe(), 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(describe() + " value contained non-utf8 characters: ", exc);
        }
    }

    @Override

View on GitHub (pinned to 88fd0f6a0e)