{"record":{"id":"1bb1e6c55e83fb46","repo":"HMCL-dev/HMCL","slug":"empty-theme-condition-value-for","errorCode":null,"errorMessage":"Empty theme condition value for ","messagePattern":"Empty theme condition value for ","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeCondition.java","lineNumber":172,"sourceCode":"    /// Normalizes and validates a condition key.\n    private static String normalizeKey(String key) {\n        Objects.requireNonNull(key);\n\n        String normalized = key.trim();\n        if (normalized.isEmpty()) {\n            throw new JsonParseException(\"Theme condition key is blank\");\n        }\n        return normalized;\n    }\n\n    /// Normalizes and validates one condition value.\n    private static String normalizeValue(String key, String value) {\n        Objects.requireNonNull(key);\n        Objects.requireNonNull(value);\n\n        String trimmed = value.trim();\n        if (trimmed.isEmpty()) {\n            throw new JsonParseException(\"Empty theme condition value for \" + key);\n        }\n        String normalized = trimmed.toLowerCase(Locale.ROOT);\n\n        return switch (key) {\n            case KEY_BRIGHTNESS -> switch (normalized) {\n                    case \"light\", \"dark\" -> normalized;\n                    default -> throw new JsonParseException(\"Unsupported brightness condition value: \" + value);\n                };\n            case KEY_OS -> normalizeOperatingSystemValue(normalized, value);\n            case KEY_LANGUAGE -> normalized;\n            default -> trimmed;\n        };\n    }\n\n    /// Normalizes an operating system condition value.\n    private static String normalizeOperatingSystemValue(String normalized, String original) {\n        String value = switch (normalized) {\n            case \"win\", \"windows\" -> \"windows\";","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemeCondition.java#L154-L190","documentation":"ThemeCondition.normalizeValue trims each condition value and rejects ones that are empty after trimming. A blank value can never match anything, so fromJson fails with this JsonParseException naming the condition key.","triggerScenarios":"A theme JSON condition value that is \"\" or \"   \", e.g. {\"os\": [\"windows\", \" \"]} or {\"language\": \"\"}, passed through ThemeCondition.fromJson (or the ThemeCondition constructor path).","commonSituations":"Hand-edited theme files with leftover empty strings after deleting a value; editors saving placeholder quotes; generators emitting empty strings when a variable is unset.","solutions":["Replace the empty string with a real value, e.g. \"os\": [\"windows\"].","Remove the empty entry from the array (or delete the condition key if no values remain).","Filter blank strings out of condition values before building the ThemeCondition.","Catch JsonParseException and point the user at the offending key in their theme file."],"exampleFix":"// before (theme.json)\n// \"os\": [\"windows\", \"\"]\n// after\n\"os\": [\"windows\"]","handlingStrategy":"validation","validationCode":"boolean ok = values.stream().allMatch(v -> v != null && !v.trim().isEmpty());","typeGuard":"static boolean hasNoBlankValues(java.util.Collection<String> values) {\n    return values.stream().allMatch(v -> v != null && !v.trim().isEmpty());\n}","tryCatchPattern":"try {\n    ThemeCondition c = ThemeCondition.fromJson(element);\n} catch (JsonParseException e) {\n    LOG.warning(\"Blank condition value: \" + e.getMessage());\n}","preventionTips":["Never leave \"\" or whitespace-only strings in condition arrays","Filter blank strings before constructing conditions","Check generator templates so unset variables don't emit empty strings","Review theme files after bulk edits that may leave empty strings"],"tags":["json","theme","condition","empty-string"],"backgroundTag":"empty-required-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"}