{"record":{"id":"90b6d6fd4514c545","repo":"Anuken/Mindustry","slug":"integer-bitfield-values-must-all-be-strings-found","errorCode":null,"errorMessage":"Integer bitfield values must all be strings. Found: ${str}","messagePattern":"Integer bitfield values must all be strings\\. Found: (.+?)","errorType":"validation","errorClass":"SerializationException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/mod/ContentParser.java","lineNumber":457,"sourceCode":"\n        private <T> T internalRead(Class<T> type, Class elementType, JsonValue jsonData, Class keyType){\n            if(type != null){\n                if(classParsers.containsKey(type)){\n                    try{\n                        return (T)classParsers.get(type).parse(type, jsonData);\n                    }catch(Exception e){\n                        if(e instanceof RuntimeException rt){\n                            throw rt;\n                        }\n                        throw new RuntimeException(e);\n                    }\n                }\n\n                //try to parse env bits\n                if((type == int.class || type == Integer.class) && jsonData.isArray()){\n                    int value = 0;\n                    for(var str : jsonData){\n                        if(!str.isString()) throw new SerializationException(\"Integer bitfield values must all be strings. Found: \" + str);\n                        String field = str.asString();\n                        value |= Reflect.<Integer>get(Env.class, field);\n                    }\n\n                    return (T)(Integer)value;\n                }\n\n                //try to parse \"item/amount\" syntax\n                if(type == ItemStack.class && jsonData.isString() && jsonData.asString().contains(\"/\")){\n                    String[] split = jsonData.asString().split(\"/\");\n\n                    return (T)fromJson(ItemStack.class, \"{item: \" + split[0] + \", amount: \" + split[1] + \"}\");\n                }\n\n                //try to parse \"payloaditem/amount\" syntax\n                if(type == PayloadStack.class && jsonData.isString() && jsonData.asString().contains(\"/\")){\n                    String[] split = jsonData.asString().split(\"/\");\n                    int number = Strings.parseInt(split[1], 1);","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/mod/ContentParser.java#L439-L475","documentation":"Thrown when parsing an int/Integer field supplied as a JSON array (env bitfield syntax): every element must be a string naming a field on the Env class. A non-string element is rejected before Reflect.get is attempted.","triggerScenarios":"A mod JSON provides an integer/bitfield field (e.g. `env`) as an array containing numbers or objects instead of Env field-name strings.","commonSituations":"Writing `env: [1, 2]` instead of `env: [\"space\", \"ground\"]`, or copying numeric bit values from documentation.","solutions":["Use string Env field names as array elements.","Verify each name corresponds to a public field on mindustry.game.Env."],"exampleFix":"// before\n\"env\": [1, 2]\n// after\n\"env\": [\"space\", \"ground\"]","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard: every element of an int bitfield array must be a string Env field name.\nboolean validBitfield(JsonValue arr) {\n    if (!arr.isArray()) return false;\n    for (var e : arr) if (!e.isString()) return false;\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Write bitfield arrays as Env field-name strings, not numbers.","Verify each name is a public field on mindustry.game.Env.","Lint array element types in mod JSON."],"tags":["modding","json","content-parser","env","bitfield"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}