{"record":{"id":"058229795b0e21a5","repo":"Anuken/Mindustry","slug":"content-json-must-be-an-object-not-a-single-value","errorCode":null,"errorMessage":"Content JSON must be an object, not a single value.","messagePattern":"Content JSON must be an object, not a single value\\.","errorType":"validation","errorClass":"SerializationException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":1035,"sourceCode":"     * @param name the name of the file without its extension\n     * @param json the json to parse\n     * @param type the type of content this is\n     * @param file file that this content is being parsed from\n     * @return the content that was parsed\n     */\n    public Content parse(LoadedMod mod, String name, String json, Fi file, ContentType type) throws Exception{\n        checkInit();\n\n        //remove extra # characters to make it valid json... apparently some people have *unquoted* # characters in their json\n        if(file.extension().equals(\"json\")){\n            json = json.replace(\"#\", \"\\\\#\");\n        }\n\n        currentFile = file;\n        currentMod = mod;\n\n        var rawValue = parser.fromJson(null, Jval.read(json).toString(Jformat.plain));\n        if(!(rawValue instanceof JsonValue value)) throw new SerializationException(\"Content JSON must be an object, not a single value.\");\n\n        if(!parsers.containsKey(type)){\n            throw new SerializationException(\"No parsers for content type '\" + type + \"'\");\n        }\n\n        boolean located = allowPatching && locate(type, name) != null;\n        Content c = parsers.get(type).parse(mod.name, name, value);\n        c.minfo.sourceFile = file;\n        toBeParsed.add(c);\n\n        if(!located){\n            c.minfo.mod = mod;\n        }\n\n        currentMod = null;\n        currentFile = null;\n        return c;\n    }","sourceCodeStart":1017,"sourceCodeEnd":1053,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L1017-L1053","documentation":"In parse(), the raw JSON is parsed and the result must be an arc JsonValue (i.e. a JSON object at top level). If the file is a bare scalar or array at the root, fromJson yields a non-JsonValue and the parser rejects it, because every content type parser expects an object to map onto fields.","triggerScenarios":"A content file whose root JSON node is a number, string, boolean, or array rather than an object.","commonSituations":"Authoring a content file as a single quoted string or array; a malformed/truncated file; accidentally saving a list of items instead of one item definition.","solutions":["Make the file's top-level JSON an object enclosed in { }.","Each content file should define exactly one content entry as an object."],"exampleFix":"// before\n[ { \"name\":\"a\" }, { \"name\":\"b\" } ]\n// after\n{ \"name\": \"a\" }  // one file per entry","handlingStrategy":"validation","validationCode":"Object raw = parser.fromJson(null, Jval.read(json).toString(Jformat.plain));\nif(!(raw instanceof JsonValue)) throw new IllegalStateException(\"Content file root must be a JSON object\");","typeGuard":"boolean isJsonObject(Object raw){ return raw instanceof JsonValue && ((JsonValue)raw).isObject(); }","tryCatchPattern":null,"preventionTips":["Start every content file with { and end with }.","One content entry per file."],"tags":["mindustry","modding","json","content-parser","root-shape"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}