apache/cassandra · error · MarshalException

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

Error message

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

What it means

AsciiType.fromJSONObject throws this when a JSON value parsed for an ascii column is not a JSON string (ClassCastException on the (String) cast). JSON numbers, booleans, objects, or arrays are rejected because ascii values must arrive as string literals. The Java type name and value are included in the message.

Source

Thrown at src/java/org/apache/cassandra/db/marshal/AsciiType.java:81

        {
            return theEncoder.encode(CharBuffer.wrap(source));
        }
        catch (CharacterCodingException exc)
        {
            throw new MarshalException(String.format("Invalid ASCII character in string literal: %s", exc));
        }
    }

    @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 an ascii 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.US_ASCII)) + '"';
        }
        catch (CharacterCodingException exc)
        {
            throw new AssertionError("ascii value contained non-ascii characters: ", exc);
        }
    }

    public CQL3Type asCQL3Type()

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Quote the value in JSON so it is a string: {"a": "123"}
  2. Cast/serialize the value to String in application code before sending JSON
  3. Change the column type to int/double if the data is truly numeric
  4. Validate JSON payload types against the schema before sending

Example fix

// before
INSERT INTO t JSON '{"a": 123}';
// after
INSERT INTO t JSON '{"a": "123"}';
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(value instanceof String)) throw new IllegalArgumentException("ascii JSON value must be a string");

Type guard

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

Try / catch

try { Term t = asciiType.fromJSONObject(parsed); } catch (MarshalException e) { if (e.getMessage().startsWith("Expected an ascii string")) { /* convert to String and retry */ } else throw e; }

Prevention

When it happens

Trigger: JSON INSERT like INSERT INTO t JSON '{"a": 123}' where a is an ascii column; fromJson() function argument that is numeric or boolean instead of string for an ascii target; programmatic use of Term.fromJSONObject with a non-String parsed object.

Common situations: Schema evolution changed a column to ascii but JSON payloads still send numbers; developers forgetting JSON numbers must be quoted for string columns; auto-generated JSON from deserializers that emit unquoted numerics.

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