{"record":{"id":"c00338b6d65379e6","repo":"Anuken/Mindustry","slug":"ui-result-entry-count-exceeds-max-entries","errorCode":null,"errorMessage":"UI result entry count exceeds max entries: ","messagePattern":"UI result entry count exceeds max entries: ","errorType":"exception","errorClass":"ArcRuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/mindustry/io/TypeIO.java","lineNumber":324,"sourceCode":"        }\n    }\n\n    public static MenuResult readMenuResult(Reads read){\n        MenuResult result = new MenuResult();\n\n        result.token = read.l();\n\n        //would be nice to count bytes but sadly that's not really viable here\n        int remainingChars = MenuResult.maxTotalStringLen;\n\n        byte exists = read.b();\n        if(exists != 0){\n            result.result = read.str(MenuResult.maxResultLen);\n            remainingChars -= result.result.length();\n        } //else, no result, remains null\n\n        int entries = read.us();\n        if(entries > MenuResult.maxTotalValues) throw new ArcRuntimeException(\"UI result entry count exceeds max entries: \" + entries);\n\n        for(int i = 0; i < entries; i++){\n            if(remainingChars <= 0) throw new ArcRuntimeException(\"Too many long strings in MenuResult, reduce your amount of elements/IDs.\");\n            String key = read.str(Math.min(remainingChars, MenuResult.maxValueLen));\n            remainingChars -= key.length();\n\n            byte type = read.b();\n\n            switch(type){\n                case 0 -> result.values.put(key, read.f());\n                case 1 ->  result.values.put(key, read.bool());\n                case 2 -> {\n                    if(remainingChars <= 0) throw new ArcRuntimeException(\"Too many long strings in MenuResult, reduce your amount of elements/IDs.\");\n                    String value = read.str(Math.min(remainingChars, MenuResult.maxValueLen));\n                    remainingChars -= value.length();\n                    result.values.put(key, value);\n                }\n                default -> throw new ArcRuntimeException(\"Unknown UI entry type: \" + type);","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/core/src/mindustry/io/TypeIO.java#L306-L342","documentation":"readMenuResult() reads a custom UI menu's returned values. It reads an unsigned short entry count and throws ArcRuntimeException if it exceeds MenuResult.maxTotalValues (500). The cap prevents a menu result from flooding the receiver with value entries.","triggerScenarios":"A menu-result packet (from a logic/UI-builder menu) reports more than 500 value entries.","commonSituations":"A custom UI menu returning too many values; a mod that builds large menus; a malicious client.","solutions":["Reduce the number of values your UI menu returns to <= 500.","Audit the menu builder design; split the menu across multiple menus if needed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before returning a menu result, ensure the value count fits the cap.\nif(menuResult.values.size() > MenuResult.maxTotalValues){\n    throw new IllegalStateException(\"Menu returns too many values: \" + menuResult.values.size());\n}","typeGuard":null,"tryCatchPattern":"try { MenuResult r = TypeIO.readMenuResult(read); }\ncatch(ArcRuntimeException e){ Log.err(\"Bad menu result\", e); con.kick(\"Invalid menu result.\"); }","preventionTips":["Design UI menus to return <= 500 values.","Validate menu-result size in your UI build code before sending."],"tags":["network","ui","menu","deserialization"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}