Anuken/Mindustry · error · RuntimeException
Too many plans:
Error message
Too many plans:
What it means
readClientPlans() reads a client-to-server preview-plan packet. It reads a short amount and throws if amount > maxPlayerPreviewPlans (1000). Clients normally truncate to this limit (NetClient.java:784, NetServer.java:1381), so exceeding it means the sender bypassed truncation or is hostile.
Source
Thrown at core/src/mindustry/io/TypeIO.java:702
write.s((short)plans.size);
//each plan should be ~7-12 bytes
for(BuildPlan plan : plans){
if(plan.breaking) throw new RuntimeException("Breaking plans should not be sent.");
write.i(Point2.pack(plan.x, plan.y));
write.s(plan.block.id);
if(plan.block.rotate){ //no need to write rotation for blocks that don't use it
write.b((byte)plan.rotation);
}
writeObject(write, validClientPlanConfig(plan.config) ? plan.config : null);
}
}
public static ClientBuildPlans readClientPlans(Reads read){
short amount = read.s();
if(amount == 0) return null;
if(amount > maxPlayerPreviewPlans) throw new RuntimeException("Too many plans: " + amount);
var result = new ClientBuildPlans();
result.ensureCapacity(Math.min(amount, maxPlayerPreviewPlans));
for(int i = 0; i < amount; i++){
int x = read.us();
int y = read.us();
Block block = Vars.content.block(read.us());
if(block == null) throw new ArcRuntimeException("Invalid block ID in block plans! Client is likely using an incorrectly configured mod.");
int rotation = (block.rotate ? read.b() : 0);
Object config = readClientPlanConfig(read);
BuildPlan plan = new BuildPlan(x, y, rotation, block, config);
result.add(plan);
}
return result;
}
static @Nullable Object readClientPlanConfig(Reads read){View on GitHub (pinned to f695ad7e60)
Solutions
- Ensure client-side truncation to maxPlayerPreviewPlans before send.
- Server: catch the RuntimeException and kick the sender.
Example fix
// before (client sends everything) previewPlansAssembling.addAll(all); // after (client truncates to the cap) int added = Math.min(all.size, maxPlayerPreviewPlans - previewPlansAssembling.size); for(int i = 0; i < added; i++) previewPlansAssembling.add(all.get(i));
Defensive patterns
Strategy: validation
Validate before calling
// Before sending preview plans, truncate to the cap.
if(plans.size > maxPlayerPreviewPlans){
throw new IllegalStateException("Too many preview plans: " + plans.size);
} Try / catch
try { ClientBuildPlans p = TypeIO.readClientPlans(read); }
catch(RuntimeException e){ Log.err("Too many client plans", e); con.kick("Invalid packet."); } Prevention
- Always truncate preview plans to 1000 client-side before sending (NetClient.java:784).
- Treat over-limit counts server-side as a modified client.
When it happens
Trigger: A client preview-plans packet's short count field exceeds 1000.
Common situations: A modified client that skips truncation; a mod; packet fuzzing.
Related errors
- Queue too long:
- Invalid array size: {}
- Invalid array size:
- Unknown plan config object type:
- Rules too long
AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14).
Data as JSON: /api/errors/0679e605238a836c.
Report an issue: GitHub.