Anuken/Mindustry · error · IllegalArgumentException

Invalid class ID for `@` detected (found: @). Potential fixe

Error message

Invalid class ID for `@` detected (found: @). Potential fixes:
- Register with `EntityMapping.register("some-unique-name", @::new)` to get an ID, and store it somewhere.
- Override `@#classId()` to return that ID.

What it means

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.

Source

Thrown at core/src/mindustry/type/UnitType.java:881

              "hover": ElevationMoveUnit::create
              "tether": BuildingTetherPayloadUnit::create
              "crawl": CrawlUnit::create
            """, name));

        // Often modders improperly only sets `constructor = ...` without mapping. Try to mitigate that.
        // In most cases, if the constructor is a Vanilla class, things should work just fine.
        if(EntityMapping.map(name) == null) EntityMapping.nameMap.put(name, constructor);

        // Sanity checks; this is an EXTREMELY COMMON pitfalls Java modders fall into.
        int classId = example.classId();
        if(
            // Check if `classId()` even points to a valid constructor...
        EntityMapping.map(classId) == null ||
        // ...or if the class doesn't register itself and uses the ID of its base class.
        classId != ((Entityc)EntityMapping.map(classId).get()).classId()
        ){
            String type = example.getClass().getSimpleName();
            throw new IllegalArgumentException(Strings.format("""
                Invalid class ID for `@` detected (found: @). Potential fixes:
                - Register with `EntityMapping.register("some-unique-name", @::new)` to get an ID, and store it somewhere.
                - Override `@#classId()` to return that ID.
                """, type, classId, type, type));
        }
    }

    void initPathType(){
        if(flowfieldPathType == -1){
            flowfieldPathType =
            naval ? Pathfinder.costNaval :
            allowLegStep ? Pathfinder.costLegs :
            flying ? Pathfinder.costNone :
            hovering ? Pathfinder.costHover :
            Pathfinder.costGround;
        }

        if(pathCost == null){

View on GitHub (pinned to f695ad7e60)

Solutions

  1. Register a unique id: int id = EntityMapping.register("my-mod-myunit", MyUnit::new); store it.
  2. Override classId() in your entity subclass to return that stored id.
  3. Ensure the registered constructor's product reports the same classId (consistency check).

Example fix

// before
public class MyUnit extends UnitEntity { } // invalid class ID

// after
public class MyUnit extends UnitEntity {
    public static int classId;
    @Override public int classId(){ return classId; }
}
// during mod init:
MyUnit.classId = EntityMapping.register("my-mod-myunit", MyUnit::new);
Defensive patterns

Strategy: validation

Validate before calling

// Verify entity ID registration consistency before use.
int id = example.classId();
Func<Entityc> factory = EntityMapping.map(id);
if(factory == null || ((Entityc)factory.get()).classId() != id) {
    throw new IllegalArgumentException("Entity class ID not registered: " + example.getClass().getName());
}

Type guard

boolean classIdConsistent(Entityc example){
    int id = example.classId();
    Func<Entityc> f = EntityMapping.map(id);
    return f != null && ((Entityc)f.get()).classId() == id;
}

Try / catch

try {
    type.checkEntityMapping(example);
} catch(IllegalArgumentException e) {
    if(e.getMessage().startsWith("Invalid class ID")) { /* register + override classId */ }
    else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Modder subclasses UnitEntity/MechUnit etc. without calling EntityMapping.register and overriding classId(); entity deserialization would then create the wrong type.

Related errors


AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14). Data as JSON: /api/errors/057c902c5cc2dbfa. Report an issue: GitHub.