{"record":{"id":"ab82afad5aa81394","repo":"Anuken/Mindustry","slug":"rules-must-be-an-object","errorCode":null,"errorMessage":"Rules must be an object!","messagePattern":"Rules must be an object!","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":788,"sourceCode":"                if(value.has(\"sector\")){\n                    //clear old value\n                    Sector prev = preset.sector;\n                    if(prev != null && prev.preset == preset){\n                        prev.preset = null;\n                    }\n                    int sector = value.getInt(\"sector\", 0) % planet.sectors.size;\n                    if(!allowPatching && sector > 0 && planet.sectors.get(sector).preset != null){\n                        throw new RuntimeException(\"Overwriting existing sectors is not allowed.\");\n                    }\n                    preset.initialize(planet, sector, true);\n                }\n\n                value.remove(\"sector\");\n                value.remove(\"planet\");\n\n                if(value.has(\"rules\")){\n                    JsonValue r = value.remove(\"rules\");\n                    if(!r.isObject()) throw new RuntimeException(\"Rules must be an object!\");\n                    preset.rules = rules -> {\n                        try{\n                            //Use standard JSON, this is not content-parser relevant\n                            JsonIO.json.readFields(rules, r);\n                        }catch(Throwable e){ //Try not to crash here, as that would be catastrophic and confusing\n                            Log.err(e);\n                        }\n                    };\n                }\n\n                readFields(preset, value);\n            });\n            return preset;\n        },\n        ContentType.planet, (TypeParser<Planet>)(mod, name, value) -> {\n            readBundle(ContentType.planet, name, value);\n            if(value.isString()) return locate(ContentType.planet, name);\n","sourceCodeStart":770,"sourceCodeEnd":806,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L770-L806","documentation":"A sector preset's optional \"rules\" field is removed from the JSON and checked: it must be a JSON object because it is later applied via JsonIO.json.readFields(Rules, r), which maps fields by name. An array or scalar cannot be field-mapped onto the Rules object.","triggerScenarios":"\"rules\" is set to an array, a string, or a number instead of an object in the preset JSON.","commonSituations":"Misunderstanding that rules are key/value pairs; pasting a rule list as an array; truncating the JSON.","solutions":["Wrap the rules in a JSON object: \"rules\": { ... }.","Consult the Rules class fields for valid keys.","If no custom rules are needed, remove the \"rules\" key."],"exampleFix":"// before\n\"rules\": [\"building\", \"pvp\"]\n// after\n\"rules\": { \"pvp\": true, \"build\": false }","handlingStrategy":"validation","validationCode":"if(value.has(\"rules\") && !value.get(\"rules\").isObject()){\n    throw new IllegalStateException(\"preset 'rules' must be a JSON object\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model rules as key/value objects, not arrays.","Reference the Rules class for valid field names."],"tags":["mindustry","modding","json","content-parser","sector-preset","rules"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}