Anuken/Mindustry · error · RuntimeException

Meshes must be objects.

Error message

Meshes must be objects.

What it means

A planet's "mesh" field must be a JSON object (a single mesh config) or a JSON array (a list of meshes). Any other type (string, number) is rejected because parseMesh() expects structured mesh configuration with a "type" discriminator.

Source

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

                }

                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);

            Planet parent = locate(ContentType.planet, value.getString("parent", ""));
            //TODO: even if allowPatching is off, this modifies the parent.
            Planet planet = new Planet(mod + "-" + name, parent, value.getFloat("radius", 1f), value.getInt("sectorSize", 0));

            value.remove("sectorSize");

            if(value.has("mesh")){
                var mesh = value.get("mesh");
                if(!mesh.isObject() && !mesh.isArray()) throw new RuntimeException("Meshes must be objects.");
                value.remove("mesh");
                planet.meshLoader = () -> {
                    //don't crash, just log an error
                    try{
                        return parseMesh(planet, mesh);
                    }catch(Exception e){
                        Log.err(e);
                        return new ShaderSphereMesh(planet, Shaders.unlit, 2);
                    }
                };
            }

            if(value.has("cloudMesh")){
                var mesh = value.get("cloudMesh");
                if(!mesh.isObject() && !mesh.isArray()) throw new RuntimeException("Meshes must be objects.");
                value.remove("cloudMesh");
                planet.cloudMeshLoader = () -> {
                    //don't crash, just log an error

View on GitHub (pinned to f695ad7e60)

Solutions

  1. Provide the mesh as an object with a "type" field, e.g. "mesh": {"type":"SunMesh", ...}.
  2. Or as an array of mesh objects for MultiMesh.
  3. Reference parseMesh() in ContentParser.java for accepted mesh type names.

Example fix

// before
"mesh": "SunMesh"
// after
"mesh": { "type": "SunMesh", "divisions": 2 }
Defensive patterns

Strategy: validation

Validate before calling

if(value.has("mesh")){
    JsonValue m = value.get("mesh");
    if(!m.isObject() && !m.isArray()) throw new IllegalStateException("planet 'mesh' must be an object or array");
}

Type guard

boolean validMesh(JsonValue m){ return m != null && (m.isObject() || m.isArray()); }

Prevention

When it happens

Trigger: "mesh": "SunMesh" (a bare string) or "mesh": 3 triggers the guard, since isObject() && isArray() both fail.

Common situations: Writing the mesh type as a string instead of an object; confusing the mesh config shape with a name reference.

Related errors


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