apache/cassandra · error · MarshalException
Expected a list (representing a set), but got a %s: %s
Error message
Expected a list (representing a set), but got a %s: %s
What it means
SetType.fromJSONObject() converts a parsed JSON value into set Terms. JSON sets are represented as arrays, so the parsed value must be a java.util.List (after optionally decoding a JSON string); any other shape — object, number, boolean — raises this MarshalException.
Source
Thrown at src/java/org/apache/cassandra/db/marshal/SetType.java:232
return bbs;
}
public List<byte[]> serializedValuesAsByteArrays(Iterator<Cell<?>> cells)
{
List<byte[]> bbs = new ArrayList<>();
while (cells.hasNext())
bbs.add(ByteBufferUtil.getArrayUnsafeNullable(cells.next().path().get(0)));
return bbs;
}
@Override
public Term fromJSONObject(Object parsed) throws MarshalException
{
if (parsed instanceof String)
parsed = JsonUtils.decodeJson((String) parsed);
if (!(parsed instanceof List))
throw new MarshalException(String.format(
"Expected a list (representing a set), but got a %s: %s", parsed.getClass().getSimpleName(), parsed));
List<?> list = (List<?>) parsed;
List<Term> terms = new ArrayList<>(list.size());
for (Object element : list)
{
if (element == null)
throw new MarshalException("Invalid null element in set");
terms.add(elements.fromJSONObject(element));
}
return new MultiElements.DelayedValue(this, terms);
}
@Override
public String toJSONString(ByteBuffer buffer, ProtocolVersion protocolVersion)
{
return setOrListToJsonString(buffer, elements, protocolVersion);View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Send a JSON array for set columns: [1,2,3] instead of {"1":1} or a scalar.
- Fix client serialization so set-typed fields emit JSON arrays.
- Catch MarshalException around JSON term conversion and validate the payload is an array before submission.
Example fix
// before
INSERT INTO t (s) JSON '{"s": {"1":1}}';
// after
INSERT INTO t (s) JSON '{"s": [1, 2, 3]}'; Defensive patterns
Strategy: type-guard
Validate before calling
if (!(parsedValue instanceof List))
throw new IllegalArgumentException("set column requires a JSON array, got: " + parsedValue); Type guard
static boolean isJsonArray(Object v) {
if (v instanceof String)
v = JsonUtils.decodeJson((String) v);
return v instanceof List;
} Try / catch
try {
Term term = setType.fromJSONObject(parsed);
} catch (MarshalException e) {
// reject payload; log offending value
} Prevention
- Emit JSON arrays for set columns
- Add JSON schema validation with type: array for set fields
- Do not send JSON objects or scalars to set columns
When it happens
Trigger: Calling fromJSONObject on SetType with a parsed Object that is not a List — e.g. a JSON object {"a":1}, a scalar 42, or true; or a string that fails JsonUtils.decodeJson into a list.
Common situations: CQL JSON inserts where a set column receives a JSON object or scalar; clients sending map-style payloads to set columns; double-encoded JSON strings.
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 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 float value, but got a %s: %s
- Expected a map, but got a %s: %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/fa024c49a0a83be9.
Report an issue: GitHub.