{"record":{"id":"52f67c85f06d00fe","repo":"Anuken/Mindustry","slug":"unknown-plan-config-object-type","errorCode":null,"errorMessage":"Unknown plan config object type: ","messagePattern":"Unknown plan config object type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/io/TypeIO.java","lineNumber":730,"sourceCode":"            Object config = readClientPlanConfig(read);\n            BuildPlan plan = new BuildPlan(x, y, rotation, block, config);\n            result.add(plan);\n        }\n\n        return result;\n    }\n\n    static @Nullable Object readClientPlanConfig(Reads read){\n        byte type = read.b();\n        return switch(type){\n            case 0 -> null;\n            case 1 -> read.i();\n            case 2 -> read.l();\n            case 3 -> read.f();\n            case 5 -> content.getByID(ContentType.all[read.b()], read.s());\n            case 10 -> read.bool();\n            case 11 -> read.d();\n            default -> throw new IllegalArgumentException(\"Unknown plan config object type: \" + type);\n        };\n    }\n\n    //for client plans, most configs aren't necessary (links are intentionally not displayed/sent)\n    static boolean validClientPlanConfig(Object o){\n        return o == null || o instanceof Number || o instanceof Boolean || o instanceof Content;\n    }\n\n    public static void writeController(Writes write, UnitController control){\n        //no real unit controller state is written, only the type\n        if(control instanceof Player p){\n            write.b(0);\n            write.i(p.id);\n        }else if(control instanceof LogicAI logic && logic.controller != null){\n            write.b(3);\n            write.i(logic.controller.pos());\n        }else if(control instanceof CommandAI ai){\n            write.b(9);","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/io/TypeIO.java#L712-L748","documentation":"readClientPlanConfig() reads a single config-type byte and switches on it; valid types are 0 (null), 1 (int), 2 (long), 3 (float), 5 (Content), 10 (boolean), 11 (double). Any other byte hits the default IllegalArgumentException. The gaps (4,6,7,8,9) are intentionally invalid for client plans.","triggerScenarios":"A client-plan config type byte is outside the set {0,1,2,3,5,10,11}.","commonSituations":"Client/server version mismatch in the client-plan config format; packet corruption; fuzzing.","solutions":["Match client and server versions.","Server: catch IllegalArgumentException and kick the sender.","Only emit config types 0,1,2,3,5,10,11 from client-plan writers."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { ClientBuildPlans p = TypeIO.readClientPlans(read); }\ncatch(IllegalArgumentException e){ Log.err(\"Unknown plan config type\", e); con.kick(\"Protocol mismatch.\"); }","preventionTips":["Keep client and server versions matched.","Only emit config types 0,1,2,3,5,10,11 from client-plan writers."],"tags":["network","build-plan","version-mismatch","deserialization"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}