apache/cassandra · error · MarshalException
Expected a map, but got a
Error message
Expected a map, but got a %s: %s
What it means
UserType.fromJSONObject expects the parsed JSON for a UDT value to be a JSON object (java.util Map). If it is any other type — after optionally decoding a string via JsonUtils.decodeJson — this MarshalException is thrown with the actual runtime type.
Solutions
- Supply the UDT value as a JSON object with field names as keys
- If passing a string, ensure it is valid JSON object syntax like '{"street":"..."}' so decodeJson succeeds
- Inspect the payload type at runtime and construct a Map<String,Object> manually
Example fix
// before
term = udt.fromJSONObject(Arrays.asList("a","b")); // Expected a map
// after
Map<String,Object> value = new HashMap<>();
value.put("field1", "a");
term = udt.fromJSONObject(value); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(parsed instanceof Map) && !(parsed instanceof String)) throw new IllegalArgumentException("UDT value must be a JSON object"); Type guard
boolean isUdtObject(Object o) { return (o instanceof Map) || (o instanceof String && ((String) o).trim().startsWith("{")); } Try / catch
try { term = udt.fromJSONObject(parsed); } catch (MarshalException e) { throw new BadRequestException("UDT field requires a JSON object"); } Prevention
- Always model UDT values as objects, never arrays or scalars
- Validate request bodies against the UDT schema
- Keep UDT JSON strings properly escaped/quoted
When it happens
Trigger: Passing a JSON array, scalar, or non-JSON string that fails decodeJson to UserType.fromJSONObject; passing a JSON-encoded UDT string with invalid embedded syntax.
Common situations: UDT column bound from a list or scalar in the application; JSON body field mis-typed as array instead of object; nested UDT where the inner value was quoted wrongly.
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 double value, but got a
- Expected a float value, but got a
- Expected a list, but got a
- Expected a list (representing a set), but got a
- Expected a long or a datestring representation of a…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f9fff6a097f5da2b.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/marshal/UserType.java:299
ByteBuffer path = cell.path().get(0);
nameComparator().validate(path);
Short fieldPosition = nameComparator().getSerializer().deserialize(path);
fieldType(fieldPosition).validate(cell.value(), cell.accessor());
}
else
{
validate(cell.value(), cell.accessor());
}
}
@Override
public Term fromJSONObject(Object parsed) throws MarshalException
{
if (parsed instanceof String)
parsed = JsonUtils.decodeJson((String) parsed);
if (!(parsed instanceof Map))
throw new MarshalException(String.format(
"Expected a map, but got a %s: %s", parsed.getClass().getSimpleName(), parsed));
Map<String, Object> map = (Map<String, Object>) parsed;
JsonUtils.handleCaseSensitivity(map);
List<Term> terms = new ArrayList<>(types.size());
Set keys = map.keySet();
assert keys.isEmpty() || keys.iterator().next() instanceof String;
int foundValues = 0;
for (int i = 0; i < types.size(); i++)
{
Object value = map.get(stringFieldNames.get(i));
if (value == null)
{
terms.add(Constants.NULL_VALUE);View on GitHub (pinned to 88fd0f6a0e)