{"record":{"id":"8efd80f16f41b7d1","repo":"Anuken/Mindustry","slug":"meshes-must-be-objects","errorCode":null,"errorMessage":"Meshes must be objects.","messagePattern":"Meshes must be objects\\.","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":815,"sourceCode":"                }\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\n            Planet parent = locate(ContentType.planet, value.getString(\"parent\", \"\"));\n            //TODO: even if allowPatching is off, this modifies the parent.\n            Planet planet = new Planet(mod + \"-\" + name, parent, value.getFloat(\"radius\", 1f), value.getInt(\"sectorSize\", 0));\n\n            value.remove(\"sectorSize\");\n\n            if(value.has(\"mesh\")){\n                var mesh = value.get(\"mesh\");\n                if(!mesh.isObject() && !mesh.isArray()) throw new RuntimeException(\"Meshes must be objects.\");\n                value.remove(\"mesh\");\n                planet.meshLoader = () -> {\n                    //don't crash, just log an error\n                    try{\n                        return parseMesh(planet, mesh);\n                    }catch(Exception e){\n                        Log.err(e);\n                        return new ShaderSphereMesh(planet, Shaders.unlit, 2);\n                    }\n                };\n            }\n\n            if(value.has(\"cloudMesh\")){\n                var mesh = value.get(\"cloudMesh\");\n                if(!mesh.isObject() && !mesh.isArray()) throw new RuntimeException(\"Meshes must be objects.\");\n                value.remove(\"cloudMesh\");\n                planet.cloudMeshLoader = () -> {\n                    //don't crash, just log an error","sourceCodeStart":797,"sourceCodeEnd":833,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L797-L833","documentation":"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.","triggerScenarios":"\"mesh\": \"SunMesh\" (a bare string) or \"mesh\": 3 triggers the guard, since isObject() && isArray() both fail.","commonSituations":"Writing the mesh type as a string instead of an object; confusing the mesh config shape with a name reference.","solutions":["Provide the mesh as an object with a \"type\" field, e.g. \"mesh\": {\"type\":\"SunMesh\", ...}.","Or as an array of mesh objects for MultiMesh.","Reference parseMesh() in ContentParser.java for accepted mesh type names."],"exampleFix":"// before\n\"mesh\": \"SunMesh\"\n// after\n\"mesh\": { \"type\": \"SunMesh\", \"divisions\": 2 }","handlingStrategy":"validation","validationCode":"if(value.has(\"mesh\")){\n    JsonValue m = value.get(\"mesh\");\n    if(!m.isObject() && !m.isArray()) throw new IllegalStateException(\"planet 'mesh' must be an object or array\");\n}","typeGuard":"boolean validMesh(JsonValue m){ return m != null && (m.isObject() || m.isArray()); }","tryCatchPattern":null,"preventionTips":["Always pass mesh config objects with a \"type\" field.","Never put a bare type string under \"mesh\"."],"tags":["mindustry","modding","json","content-parser","planet","mesh"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}