{"record":{"id":"322cf9f8332a1c63","repo":"HMCL-dev/HMCL","slug":"missing-protected-payload-member-protection","errorCode":null,"errorMessage":"Missing protected payload member: protection","messagePattern":"Missing protected payload member: protection","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java","lineNumber":339,"sourceCode":"        /// @return the selected write mode\n        static ProtectionMode fromConfiguredId(@Nullable String id) {\n            for (ProtectionMode mode : values()) {\n                if (mode.id.equals(id)) {\n                    return mode;\n                }\n            }\n            return OBFUSCATED_V1;\n        }\n\n        /// Reads the protection mode from an envelope.\n        ///\n        /// @param envelope the envelope object to inspect\n        /// @return the protection mode declared by the envelope\n        /// @throws JsonParseException if the declared protection mode is unsupported\n        static ProtectionMode fromEnvelope(JsonObject envelope) {\n            String protection = JsonUtils.getString(envelope, PROPERTY_PROTECTION);\n            if (protection == null) {\n                throw new JsonParseException(\"Missing protected payload member: protection\");\n            }\n\n            for (ProtectionMode mode : values()) {\n                if (mode.id.equals(protection)) {\n                    return mode;\n                }\n            }\n            throw new JsonParseException(\"Unsupported protected payload: \" + protection);\n        }\n    }\n\n    /// Reads and reveals a protected JSON payload from an envelope object.\n    ///\n    /// @param envelope the envelope object to read from\n    /// @param payloadType the expected JSON element type\n    /// @return the revealed JSON payload\n    /// @param <T> the expected JSON element type\n    /// @throws JsonParseException if the envelope is malformed or cannot be revealed","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/setting/ProtectedPayload.java#L321-L357","documentation":"ProtectionMode.fromEnvelope reads the required 'protection' member of a protected-payload JSON envelope and maps it to a ProtectionMode enum value. If the member is absent, it throws JsonParseException because the envelope cannot declare how its payload was protected, so deserialization cannot proceed safely.","triggerScenarios":"Calling ProtectedPayload reading APIs with a JsonObject that lacks the 'protection' property — e.g. a hand-written or truncated envelope, or JSON produced by an older/newer schema version that renamed or removed the member.","commonSituations":"Manually editing the settings/config file and deleting the protection field; copying an envelope from another format; schema drift between HMCL versions.","solutions":["Restore the 'protection' member to the envelope JSON with the correct protection-mode id","Regenerate the envelope via the library's own serialization path instead of hand-editing the file","Check for schema/version mismatch and upgrade or downgrade the file to the format this HMCL version expects","Catch JsonParseException in the caller and fall back to re-creating the payload"],"exampleFix":"// before\n{\"payload\":\"...\"}\n// after\n{\"protection\":\"none\",\"payload\":\"...\"}","handlingStrategy":"validation","validationCode":"if (envelope == null || !envelope.has(\"protection\")) { throw new IllegalArgumentException(\"envelope must contain 'protection'\"); }","typeGuard":"static boolean hasProtection(JsonObject envelope) { return envelope != null && envelope.has(\"protection\") && envelope.get(\"protection\").isJsonPrimitive(); }","tryCatchPattern":"try { mode = ProtectionMode.fromEnvelope(envelope); } catch (JsonParseException e) { LOG.warning(\"Envelope missing/invalid protection member\", e); }","preventionTips":["Generate envelopes only via the library's own writers","Diff config files against the schema after manual edits","Pin HMCL versions across machines sharing config files"],"tags":["json","config","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}