{"record":{"id":"915d37f424f9d4b5","repo":"apache/cassandra","slug":"expected-a-map-but-got-a-s-s","errorCode":null,"errorMessage":"Expected a map, but got a %s: %s","messagePattern":"Expected a map, but got a (.+?): (.+?)","errorType":"exception","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/MapType.java","lineNumber":339,"sourceCode":"        assert isMultiCell;\n        List<byte[]> bbs = new ArrayList<>();\n        while (cells.hasNext())\n        {\n            Cell<?> c = cells.next();\n            bbs.add(ByteBufferUtil.getArrayUnsafeNullable(c.path().get(0)));\n            bbs.add(c.valueAsArray());\n        }\n        return bbs;\n    }\n\n    @Override\n    public Term fromJSONObject(Object parsed) throws MarshalException\n    {\n        if (parsed instanceof String)\n            parsed = JsonUtils.decodeJson((String) parsed);\n\n        if (!(parsed instanceof Map))\n            throw new MarshalException(String.format(\n                    \"Expected a map, but got a %s: %s\", parsed.getClass().getSimpleName(), parsed));\n\n        Map<?, ?> map = (Map<?, ?>) parsed;\n        List<Term> terms = new ArrayList<>(map.size() << 1);\n        for (Map.Entry<?, ?> entry : map.entrySet())\n        {\n            if (entry.getKey() == null)\n                throw new MarshalException(\"Invalid null key in map\");\n\n            if (entry.getValue() == null)\n                throw new MarshalException(\"Invalid null value in map\");\n\n            terms.add(keys.fromJSONObject(entry.getKey()));\n            terms.add(values.fromJSONObject(entry.getValue()));\n        }\n        return new MultiElements.DelayedValue(this, terms);\n    }\n","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/MapType.java#L321-L357","documentation":"MapType.fromJSONObject() converts a parsed JSON value into collection Terms. Because JSON objects decode to Java Maps, the value must be a Map; if it is any other type (after optionally decoding a JSON string), the library throws this MarshalException.","triggerScenarios":"Calling fromJSONObject on MapType with a parsed Object that is not a java.util.Map — e.g. a List, Number, Boolean, or a String that fails to decode to a JSON object via JsonUtils.decodeJson.","commonSituations":"CQL JSON inserts where a map column is given an array or scalar instead of a JSON object; client code passing a JSON array like [1,2] to a map<int,text> column; double-encoded JSON strings.","solutions":["Provide a JSON object for map columns: {\"1\":\"one\"} instead of [1,2] or a scalar.","Fix client serialization so map-typed fields emit JSON objects.","Catch MarshalException around the JSON term conversion and validate the payload shape before submission."],"exampleFix":"// before\nINSERT INTO t (m) JSON '{\"m\": [1,2]}';\n// after\nINSERT INTO t (m) JSON '{\"m\": {\"1\":\"a\", \"2\":\"b\"}}';","handlingStrategy":"type-guard","validationCode":"if (!(parsedValue instanceof Map))\n    throw new IllegalArgumentException(\"map column requires a JSON object, got: \" + parsedValue);","typeGuard":"static boolean isJsonObject(Object v) {\n    if (v instanceof String)\n        v = JsonUtils.decodeJson((String) v);\n    return v instanceof Map;\n}","tryCatchPattern":"try {\n    Term term = mapType.fromJSONObject(parsed);\n} catch (MarshalException e) {\n    // reject payload; log offending value\n}","preventionTips":["Emit JSON objects (not arrays) for map columns","Add JSON schema validation with type: object for map fields","Check client serializer config for map/array mapping"],"tags":["cassandra","json","map","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}