{"record":{"id":"bc87d8ed3c0e947f","repo":"HMCL-dev/HMCL","slug":"missing-payload-or-payload-array-is-too-small","errorCode":null,"errorMessage":"Missing payload or payload array is too small","messagePattern":"Missing payload or payload array is too small","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java","lineNumber":186,"sourceCode":"                    int start = laneIndex * laneLength;\n                    String lane = payload.substring(start, start + laneLength);\n                    for (int i = 0; i < LANE_PADDING_COUNT; i++) {\n                        result.add(JsonNull.INSTANCE);\n                    }\n                    result.add(lane);\n                }\n                return result;\n            }\n\n            /// Joins Base64 payload lanes from the envelope.\n            ///\n            /// @param envelope the envelope object to read from\n            /// @return the restored Base64 payload\n            /// @throws JsonParseException if the payload lanes are missing or malformed\n            private static String joinObfuscatedPayload(JsonObject envelope) {\n                if (!(envelope.get(PROPERTY_PAYLOAD) instanceof JsonArray lanes)\n                        || lanes.size() < OBFUSCATED_LANE_COUNT) {\n                    throw new JsonParseException(\"Missing payload or payload array is too small\");\n                }\n\n                int effectivePayloadSize = Integer.highestOneBit(lanes.size());\n                String[] laneTexts = new String[OBFUSCATED_LANE_COUNT];\n                int totalLength = 0;\n                for (int i = 0; i < OBFUSCATED_LANE_COUNT; i++) {\n                    int payloadIndex = lanePayloadIndex(i, effectivePayloadSize);\n                    JsonElement lane = lanes.get(payloadIndex);\n                    if (!lane.isJsonPrimitive() || !lane.getAsJsonPrimitive().isString()) {\n                        throw new JsonParseException(\"Protected payload lane is not a string\");\n                    }\n\n                    laneTexts[i] = lane.getAsString();\n                    totalLength += laneTexts[i].length();\n                }\n\n                StringBuilder result = new StringBuilder(totalLength);\n                for (String laneText : laneTexts) {","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java#L168-L204","documentation":"OBFUSCATED_V1.joinObfuscatedPayload throws this when the envelope's 'payload' member is not a JSON array or has fewer than 4 elements. The obfuscated format stores the Base64 ciphertext in a 256-element null-padded array; anything smaller cannot contain the 4 lanes and is considered malformed.","triggerScenarios":"Calling ProtectedPayload.read on an envelope marked 'hmcl-obfuscated-v1' whose payload member is missing, not an array (e.g. a plain value from PLAIN mode), or an array with fewer than OBFUSCATED_LANE_COUNT (4) entries.","commonSituations":"Mixing envelope formats — using a 'plain'-style payload with an 'hmcl-obfuscated-v1' marker; hand-editing and shortening the padded array; older or third-party writers emitting a different obfuscation layout.","solutions":["Ensure the protection marker matches the actual payload layout; use 'plain' with a direct payload, or a full obfuscated array.","Restore the original 256-element padded array (or the whole file) from backup and let HMCL re-save.","Regenerate the setting so HMCL rewrites the envelope in the correct format."],"exampleFix":"// before: mismatched marker/layout\n{\"protection\":\"hmcl-obfuscated-v1\",\"payload\":\"abc...\",\"nonce\":\"...\"}\n// after: correct pairing\n{\"protection\":\"plain\",\"payload\":{...}}","handlingStrategy":"validation","validationCode":"com.google.gson.JsonElement p = envelope.get(\"payload\");\nboolean ok = \"hmcl-obfuscated-v1\".equals(JsonUtils.getString(envelope, \"protection\"))\n        ? p instanceof com.google.gson.JsonArray && ((com.google.gson.JsonArray) p).size() >= 4\n        : p != null;","typeGuard":"static boolean hasObfuscatedPayloadArray(com.google.gson.JsonObject envelope) {\n    return envelope.get(\"payload\") instanceof com.google.gson.JsonArray lanes\n        && lanes.size() >= 4;\n}","tryCatchPattern":"try {\n    return ProtectedPayload.read(envelope, JsonObject.class);\n} catch (com.google.gson.JsonParseException e) {\n    logger.warning(\"Malformed obfuscated envelope; regenerating\", e);\n    return recreateSetting();\n}","preventionTips":["Match the protection marker to the actual payload layout (plain vs obfuscated).","Never shrink or reorder the 256-element payload array.","Validate envelopes programmatically after external tools modify them.","Regenerate settings rather than hand-crafting obfuscated envelopes."],"tags":["json","envelope-format","deserialization"],"backgroundTag":"invalid-config-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}