Anuken/Mindustry · error · IllegalArgumentException

Unknown revision ' ' for entity type

Error message

Unknown revision '{REV}' for entity type '{name}'

What it means

Generated by the Mindustry annotation processor (EntityIO) into entity read() methods. Entity serialization tracks revisions: each known revision maps to a set of field reads. The generated code handles revisions in if/else branches; the final 'else' throws IllegalArgumentException with the unknown REV. This means the saved entity data carries a revision number the generated reader was not built to understand.

Solutions

  1. Update to the game build that wrote the save (newer builds know higher revisions).
  2. If you maintain entity revisions, verify your @EntityDef / RevisionField declarations match the writer side.
  3. Do not downgrade saves across versions that changed entity field revisions; migrate forward instead.
  4. Regenerate entity sources (rebuild) so the annotation processor emits the current revision branches.

Example fix

// before: older build reading newer save -> generated else branch throws
// after: rebuild against current annotations, or load in the build that authored the save
// (no runtime patch; revision branches are compile-time generated)
Defensive patterns

Strategy: try-catch

Validate before calling

// not possible at runtime: revisions are baked into generated code
// guard by checking save version compatibility before deserializing entities
if(saveVersion > currentMaxVersion){
    throw new IOException("Save from a newer version; cannot read entity revisions");
}

Try / catch

try{ entity.read(reads); }catch(IllegalArgumentException e){ Log.err("Entity revision unknown", e); /* discard entity */ }

Prevention

When it happens

Trigger: Deserializing an entity whose saved revision is greater than the highest revision the compiled entity code knows. The literal in the message ('for entity type <name>') is baked in at annotation-processing time, while REV is the runtime value read from the stream.

Common situations: Loading a save created by a newer game build (which bumped the entity revision) on an older build; partial rebuild where entity revision metadata drifted; mixing entity classes compiled against different annotation-processor versions.

Related errors


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

Appendix: source

Thrown at annotations/src/main/java/mindustry/annotations/entity/EntityIO.java:121

                //check for the right revision
                Revision rev = revisions.get(i);
                if(i == 0){
                    cont("if(REV == $L)", rev.version);
                }else{
                    ncont("else if(REV == $L)", rev.version);
                }

                //add code for reading revision
                for(RevisionField field : rev.fields){
                    if(fieldHasAnno(field, allFields, NoSerialize.class)) continue;
                    //if the field doesn't exist, the result will be an empty string, it won't get assigned
                    io(field.type, presentFields.contains(field.name) ? "this." + field.name + " = " : "", false);
                }
            }

            //throw exception on illegal revisions
            ncont("else");
            st("throw new IllegalArgumentException(\"Unknown revision '\" + REV + \"' for entity type '" + name + "'\")");
            econt();
        }
    }

    boolean fieldHasAnno(RevisionField field, Seq<Svar> allFields, Class<? extends Annotation> type){
        Svar var = allFields.find(s -> s.name().equals(field.name));
        return var != null && var.has(type);
    }

    void writeSync(MethodSpec.Builder method, boolean write, Seq<Svar> allFields) throws Exception{
        this.method = method;
        this.write = write;

        if(write){
            //write uses most recent revision
            for(RevisionField field : revisions.peek().fields){
                if(fieldHasAnno(field, allFields, NoSync.class)) continue;

View on GitHub (pinned to f695ad7e60)