Anuken/Mindustry · error · RuntimeException

Rules must be an object!

Error message

Rules must be an object!

What it means

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.

Source

Thrown at core/src/mindustry/mod/ContentParser.java:788

                if(value.has("sector")){
                    //clear old value
                    Sector prev = preset.sector;
                    if(prev != null && prev.preset == preset){
                        prev.preset = null;
                    }
                    int sector = value.getInt("sector", 0) % planet.sectors.size;
                    if(!allowPatching && sector > 0 && planet.sectors.get(sector).preset != null){
                        throw new RuntimeException("Overwriting existing sectors is not allowed.");
                    }
                    preset.initialize(planet, sector, true);
                }

                value.remove("sector");
                value.remove("planet");

                if(value.has("rules")){
                    JsonValue r = value.remove("rules");
                    if(!r.isObject()) throw new RuntimeException("Rules must be an object!");
                    preset.rules = rules -> {
                        try{
                            //Use standard JSON, this is not content-parser relevant
                            JsonIO.json.readFields(rules, r);
                        }catch(Throwable e){ //Try not to crash here, as that would be catastrophic and confusing
                            Log.err(e);
                        }
                    };
                }

                readFields(preset, value);
            });
            return preset;
        },
        ContentType.planet, (TypeParser<Planet>)(mod, name, value) -> {
            readBundle(ContentType.planet, name, value);
            if(value.isString()) return locate(ContentType.planet, name);

View on GitHub (pinned to f695ad7e60)

Solutions

  1. Wrap the rules in a JSON object: "rules": { ... }.
  2. Consult the Rules class fields for valid keys.
  3. If no custom rules are needed, remove the "rules" key.

Example fix

// before
"rules": ["building", "pvp"]
// after
"rules": { "pvp": true, "build": false }
Defensive patterns

Strategy: validation

Validate before calling

if(value.has("rules") && !value.get("rules").isObject()){
    throw new IllegalStateException("preset 'rules' must be a JSON object");
}

Prevention

When it happens

Trigger: "rules" is set to an array, a string, or a number instead of an object in the preset JSON.

Common situations: Misunderstanding that rules are key/value pairs; pasting a rule list as an array; truncating the JSON.

Related errors


AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14). Data as JSON: /api/errors/ab82afad5aa81394. Report an issue: GitHub.