{"record":{"id":"057c902c5cc2dbfa","repo":"Anuken/Mindustry","slug":"invalid-class-id-for-detected-found-pote","errorCode":null,"errorMessage":"Invalid class ID for `@` detected (found: @). Potential fixes:\n- Register with `EntityMapping.register(\"some-unique-name\", @::new)` to get an ID, and store it somewhere.\n- Override `@#classId()` to return that ID.","messagePattern":"Invalid class ID for `@` detected \\(found: @\\)\\. Potential fixes:\n- Register with `EntityMapping\\.register\\(\"some-unique-name\", @::new\\)` to get an ID, and store it somewhere\\.\n- Override `@#classId\\(\\)` to return that ID\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/type/UnitType.java","lineNumber":881,"sourceCode":"              \"hover\": ElevationMoveUnit::create\n              \"tether\": BuildingTetherPayloadUnit::create\n              \"crawl\": CrawlUnit::create\n            \"\"\", name));\n\n        // Often modders improperly only sets `constructor = ...` without mapping. Try to mitigate that.\n        // In most cases, if the constructor is a Vanilla class, things should work just fine.\n        if(EntityMapping.map(name) == null) EntityMapping.nameMap.put(name, constructor);\n\n        // Sanity checks; this is an EXTREMELY COMMON pitfalls Java modders fall into.\n        int classId = example.classId();\n        if(\n            // Check if `classId()` even points to a valid constructor...\n        EntityMapping.map(classId) == null ||\n        // ...or if the class doesn't register itself and uses the ID of its base class.\n        classId != ((Entityc)EntityMapping.map(classId).get()).classId()\n        ){\n            String type = example.getClass().getSimpleName();\n            throw new IllegalArgumentException(Strings.format(\"\"\"\n                Invalid class ID for `@` detected (found: @). Potential fixes:\n                - Register with `EntityMapping.register(\"some-unique-name\", @::new)` to get an ID, and store it somewhere.\n                - Override `@#classId()` to return that ID.\n                \"\"\", type, classId, type, type));\n        }\n    }\n\n    void initPathType(){\n        if(flowfieldPathType == -1){\n            flowfieldPathType =\n            naval ? Pathfinder.costNaval :\n            allowLegStep ? Pathfinder.costLegs :\n            flying ? Pathfinder.costNone :\n            hovering ? Pathfinder.costHover :\n            Pathfinder.costGround;\n        }\n\n        if(pathCost == null){","sourceCodeStart":863,"sourceCodeEnd":899,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/type/UnitType.java#L863-L899","documentation":"After a constructor is set, checkEntityMapping verifies the entity's classId maps to a valid constructor in EntityMapping AND that the class's own classId() points back to a constructor whose entity's classId() matches (i.e. the class registered its own ID). This catches the common pitfall of subclassing a unit entity without registering an ID.","triggerScenarios":"A custom unit entity subclass either has no EntityMapping entry for its classId, or its classId collides with the base class because it never registered/overrode the ID.","commonSituations":"Modder subclasses UnitEntity/MechUnit etc. without calling EntityMapping.register and overriding classId(); entity deserialization would then create the wrong type.","solutions":["Register a unique id: int id = EntityMapping.register(\"my-mod-myunit\", MyUnit::new); store it.","Override classId() in your entity subclass to return that stored id.","Ensure the registered constructor's product reports the same classId (consistency check)."],"exampleFix":"// before\npublic class MyUnit extends UnitEntity { } // invalid class ID\n\n// after\npublic class MyUnit extends UnitEntity {\n    public static int classId;\n    @Override public int classId(){ return classId; }\n}\n// during mod init:\nMyUnit.classId = EntityMapping.register(\"my-mod-myunit\", MyUnit::new);","handlingStrategy":"validation","validationCode":"// Verify entity ID registration consistency before use.\nint id = example.classId();\nFunc<Entityc> factory = EntityMapping.map(id);\nif(factory == null || ((Entityc)factory.get()).classId() != id) {\n    throw new IllegalArgumentException(\"Entity class ID not registered: \" + example.getClass().getName());\n}","typeGuard":"boolean classIdConsistent(Entityc example){\n    int id = example.classId();\n    Func<Entityc> f = EntityMapping.map(id);\n    return f != null && ((Entityc)f.get()).classId() == id;\n}","tryCatchPattern":"try {\n    type.checkEntityMapping(example);\n} catch(IllegalArgumentException e) {\n    if(e.getMessage().startsWith(\"Invalid class ID\")) { /* register + override classId */ }\n    else throw e;\n}","preventionTips":["Register custom entity classes with EntityMapping.register at mod init.","Override classId() to return the registered id.","Keep the registered constructor and classId() mutually consistent."],"tags":["modding","units","entities","registration","serialization"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}