{"record":{"id":"1132b89496b75978","repo":"HMCL-dev/HMCL","slug":"theme-background-field-is-missing","errorCode":null,"errorMessage":"Theme background field is missing: ","messagePattern":"Theme background field is missing: ","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeBackground.java","lineNumber":128,"sourceCode":"        };\n    }\n\n    /// Reads an optional string field.\n    private static @Nullable String readString(JsonObject object, String field) {\n        JsonElement element = object.get(field);\n        if (element == null) {\n            return null;\n        }\n        if (!(element instanceof JsonPrimitive primitive) || !primitive.isString()) {\n            throw new JsonParseException(\"Theme background field must be a string: \" + field);\n        }\n        return primitive.getAsString();\n    }\n\n    /// Returns a required non-blank string value.\n    private static String requireNonBlank(@Nullable String value, String field) {\n        if (value == null) {\n            throw new JsonParseException(\"Theme background field is missing: \" + field);\n        }\n        String trimmed = value.trim();\n        if (trimmed.isEmpty()) {\n            throw new JsonParseException(\"Theme background field is blank: \" + field);\n        }\n        return trimmed;\n    }\n\n    /// A source that delegates to HMCL's launcher default background resolution.\n    @NotNullByDefault\n    record Default() implements ThemeBackground {\n        /// Adds this source to a JSON object.\n        @Override\n        public void addToJsonObject(JsonObject object) {\n            object.addProperty(FIELD_TYPE, \"default\");\n        }\n\n    }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeBackground.java#L110-L146","documentation":"ThemeBackground.requireNonBlank throws this JsonParseException when a required source field is absent (null) while constructing a Builtin, Image, or Paint background. It fires when a constructor receives a null value for its mandatory field — e.g. {\"type\":\"image\"} with no \"path\" — because the record's compact constructor delegates to requireNonBlank.","triggerScenarios":"fromJson on {\"type\":\"builtin\"} with no \"id\" only if code passes null to the Builtin(String) constructor path requiring it — concretely, constructing new Image(null), new Paint(null), or new Builtin with a null id via a code path that requires it, or JSON like {\"type\":\"image\"} where path resolves to null for the Image record constructor.","commonSituations":"Theme manifests where the \"type\" was set but the matching value field was forgotten ({\"type\":\"image\"} with no \"path\"), or programmatic construction of records with null required arguments.","solutions":["Add the required field for the declared type: \"id\" for builtin, \"path\" for image, \"paint\" for paint","Use type \"default\" or \"theme_color\" instead if no concrete source value exists","For programmatic construction, pass a non-null string or use the no-arg Builtin() fallback constructor"],"exampleFix":"// before\n{\"type\": \"image\"}\n// after\n{\"type\": \"image\", \"path\": \"assets/bg.png\"}","handlingStrategy":"validation","validationCode":"if (obj.has(\"type\")) {\n    String t = obj.get(\"type\").getAsString().toUpperCase(Locale.ROOT);\n    String need = switch (t) { case \"IMAGE\" -> \"path\"; case \"PAINT\" -> \"paint\"; case \"BUILTIN\" -> \"id\"; default -> null; };\n    if (need != null && !obj.has(need)) throw new IllegalArgumentException(\"missing field for type \" + t + \": \" + need);\n}","typeGuard":null,"tryCatchPattern":"try { ThemeBackground.fromJson(obj); } catch (JsonParseException e) { LOG.warning(\"Background field missing: \" + e.getMessage()); }","preventionTips":["Pair each concrete type with its required value field (image->path, paint->paint, builtin->id)","Use \"default\"/\"theme_color\" when no concrete value is available","Generate backgrounds via records + toJsonObject() instead of raw JSON"],"tags":["json","missing-field","theme-config"],"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"}