{"record":{"id":"6da2fb97cf799782","repo":"Anuken/Mindustry","slug":"queue-too-long","errorCode":null,"errorMessage":"Queue too long: ","messagePattern":"Queue too long: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/io/TypeIO.java","lineNumber":594,"sourceCode":"    //on the network, plans must be capped by size\n    public static void writePlansQueueNet(Writes write, Queue<BuildPlan> plans){\n        if(plans == null){\n            write.i(-1);\n            return;\n        }\n\n        int used = getMaxPlans(plans);\n\n        write.i(used);\n        for(int i = 0; i < used; i++){\n            writePlan(write, plans.get(i));\n        }\n    }\n\n    public static Queue<BuildPlan> readPlansQueueNet(Reads read){\n        int used = read.i();\n        if(used == -1) return null;\n        if(used > maxSyncedPlans) throw new RuntimeException(\"Queue too long: \" + used);\n        var out = new Queue<BuildPlan>();\n        for(int i = 0; i < used; i++){\n            out.add(readPlan(read));\n        }\n        return out;\n    }\n\n    public static Queue<BuildPlan> readPlansQueue(Reads read){\n        int used = read.i();\n        if(used == -1) return null;\n        //this is ONLY used in saves, so don't enforce a max size, it can be anything.\n        var out = new Queue<BuildPlan>();\n        for(int i = 0; i < used; i++){\n            out.add(readPlan(read));\n        }\n        return out;\n    }\n","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/io/TypeIO.java#L576-L612","documentation":"readPlansQueueNet() reads a network-synced build-plan queue. After reading an int count it throws if count > maxSyncedPlans (20). This caps how many BuildPlans a single sync packet can carry to bound processing and bandwidth. Note the save-path readPlansQueue (TypeIO.java:602) deliberately has no cap.","triggerScenarios":"A build-plan sync packet's int count field exceeds 20.","commonSituations":"A client queueing more than 20 plans in one sync; a buggy mod; a malicious client.","solutions":["Limit the number of plans queued/sent per network sync to <= 20.","Server: catch the RuntimeException and kick the sender."],"exampleFix":"// before\nqueue.addAll(manyPlans); // > 20 in one sync\nTypeIO.writePlansQueueNet(write, queue);\n\n// after\nQueue<BuildPlan> capped = new Queue<>();\nfor(int i = 0; i < Math.min(maxSyncedPlans, manyPlans.size); i++) capped.add(manyPlans.get(i));\nTypeIO.writePlansQueueNet(write, capped);","handlingStrategy":"validation","validationCode":"// Before syncing, ensure the queue fits the network cap.\nif(plans.size > 20){\n    throw new IllegalStateException(\"Too many plans to sync: \" + plans.size);\n}","typeGuard":null,"tryCatchPattern":"try { Queue<BuildPlan> q = TypeIO.readPlansQueueNet(read); }\ncatch(RuntimeException e){ Log.err(\"Build-plan sync too long\", e); con.kick(\"Invalid packet.\"); }","preventionTips":["Batch build-plan syncs in chunks of <= 20.","Use readPlansQueue only for saves; it has no cap and is not net-safe."],"tags":["network","build-plan","deserialization","security"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}