{"record":{"id":"f9fff6a097f5da2b","repo":"apache/cassandra","slug":"expected-a-map-but-got-a-s-s-f9fff6","errorCode":null,"errorMessage":"Expected a map, but got a %s: %s","messagePattern":"Expected a map, but got a (.+?): (.+?)","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/UserType.java","lineNumber":299,"sourceCode":"            ByteBuffer path = cell.path().get(0);\n            nameComparator().validate(path);\n            Short fieldPosition = nameComparator().getSerializer().deserialize(path);\n            fieldType(fieldPosition).validate(cell.value(), cell.accessor());\n        }\n        else\n        {\n            validate(cell.value(), cell.accessor());\n        }\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<String, Object> map = (Map<String, Object>) parsed;\n\n        JsonUtils.handleCaseSensitivity(map);\n\n        List<Term> terms = new ArrayList<>(types.size());\n\n        Set keys = map.keySet();\n        assert keys.isEmpty() || keys.iterator().next() instanceof String;\n\n        int foundValues = 0;\n        for (int i = 0; i < types.size(); i++)\n        {\n            Object value = map.get(stringFieldNames.get(i));\n            if (value == null)\n            {\n                terms.add(Constants.NULL_VALUE);","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/UserType.java#L281-L317","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nterm = udt.fromJSONObject(Arrays.asList(\"a\",\"b\")); // Expected a map\n// after\nMap<String,Object> value = new HashMap<>();\nvalue.put(\"field1\", \"a\");\nterm = udt.fromJSONObject(value);","handlingStrategy":"type-guard","validationCode":"if (!(parsed instanceof Map) && !(parsed instanceof String)) throw new IllegalArgumentException(\"UDT value must be a JSON object\");","typeGuard":"boolean isUdtObject(Object o) { return (o instanceof Map) || (o instanceof String && ((String) o).trim().startsWith(\"{\")); }","tryCatchPattern":"try { term = udt.fromJSONObject(parsed); } catch (MarshalException e) { throw new BadRequestException(\"UDT field requires a JSON object\"); }","preventionTips":["Always model UDT values as objects, never arrays or scalars","Validate request bodies against the UDT schema","Keep UDT JSON strings properly escaped/quoted"],"tags":["cassandra","udt","json","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-17T15:17:12.973Z"}