{"record":{"id":"920caedefe8cd663","repo":"Anuken/Mindustry","slug":"attribute-definitions-must-be-objects-e-g-heat","errorCode":null,"errorMessage":"Attribute definitions must be objects, e.g. {heat: 10}","messagePattern":"Attribute definitions must be objects, e\\.g\\. (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":96,"sourceCode":"            }\n            Class<? extends Effect> bc = resolve(data.getString(\"type\", \"\"), ParticleEffect.class);\n            data.remove(\"type\");\n            Effect result = make(bc);\n            readFields(result, data);\n            return result;\n        });\n        put(Sortf.class, (type, data) -> field(UnitSorts.class, data));\n        put(Interp.class, (type, data) -> field(Interp.class, data));\n        put(Blending.class, (type, data) -> field(Blending.class, data));\n        put(CacheLayer.class, (type, data) -> field(CacheLayer.class, data));\n        put(Attribute.class, (type, data) -> {\n            String attr = data.asString();\n            if(Attribute.exists(attr)) return Attribute.get(attr);\n            return Attribute.add(attr);\n        });\n        put(Attributes.class, (type, data) -> {\n            if(!data.isObject()){\n                throw new IllegalArgumentException(\"Attribute definitions must be objects, e.g. {heat: 10}\");\n            }\n            Attributes attr = new Attributes();\n            for(var child : data){\n                Attribute value = Attribute.exists(child.name) ? Attribute.get(child.name) : Attribute.add(child.name);\n                attr.set(value, child.asFloat());\n            }\n            return attr;\n        });\n        put(BuildVisibility.class, (type, data) -> field(BuildVisibility.class, data));\n        put(Schematic.class, (type, data) -> {\n            Object result = fieldOpt(Loadouts.class, data);\n            if(result != null){\n                return result;\n            }else{\n                String str = data.asString();\n                if(str.startsWith(Vars.schematicBaseStart)){\n                    return Schematics.readBase64(str);\n                }else{","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L78-L114","documentation":"Thrown by the Attributes parser in ContentParser when the JSON value for an Attributes-typed field is not a JSON object. Attributes is a name->float map (e.g. {heat: 10}), so strings, numbers, or arrays are invalid.","triggerScenarios":"A mod JSON block sets an `attributes` field (or any Attributes-typed field) to a non-object value such as \"heat\", 10, or [1,2].","commonSituations":"Mod authors copy the wrong example, pass a single attribute name string instead of a map, or confuse Attributes with a single Attribute.","solutions":["Rewrite the value as a JSON object mapping attribute names to floats.","Verify each attribute name either exists or will be auto-added via Attribute.add.","Distinguish Attributes (the map) from a single Attribute reference (which accepts a string)."],"exampleFix":"// before\n\"attributes\": \"heat\"\n// after\n\"attributes\": { \"heat\": 10 }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard: Attributes must be a JSON object (map of name->float).\nboolean validAttributes(JsonValue v) {\n    return v.isObject();\n}","tryCatchPattern":null,"preventionTips":["Author attributes as { name: value } objects, never bare strings/numbers.","Cross-check attribute names against the Attribute registry.","Use a JSON schema/linter for mod content files."],"tags":["modding","json","content-parser","attributes"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}