{"record":{"id":"92fa48015ee22a31","repo":"halo-dev/halo","slug":"no-value-present-for-label-key-92fa48","errorCode":null,"errorMessage":"No value present for label key: {}","messagePattern":"No value present for label key: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/run/halo/app/extension/router/selector/LabelSelectorConverter.java","lineNumber":38,"sourceCode":"                return Queries.labelEqual(criteria.key(), getSingleValue(criteria))\n                        .not();\n            }\n            case NotExist -> {\n                return Queries.labelExists(criteria.key()).not();\n            }\n            case Exist -> {\n                return Queries.labelExists(criteria.key());\n            }\n            case IN -> {\n                return Queries.labelIn(criteria.key(), defaultIfNull(criteria.values(), Set.of()));\n            }\n            default -> throw new IllegalArgumentException(\"Unsupported operator: \" + criteria.operator());\n        }\n    }\n\n    String getSingleValue(SelectorCriteria criteria) {\n        if (CollectionUtils.isEmpty(criteria.values())) {\n            throw new IllegalArgumentException(\"No value present for label key: \" + criteria.key());\n        }\n        return criteria.values().iterator().next();\n    }\n}\n","sourceCodeStart":20,"sourceCodeEnd":43,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/api/src/main/java/run/halo/app/extension/router/selector/LabelSelectorConverter.java#L20-L43","documentation":"Thrown by LabelSelectorConverter.getSingleValue when an Equals or NotEquals SelectorCriteria has an empty/null values collection. Equals/NotEquals label queries need exactly one value; with none, the converter cannot build Queries.labelEqual and throws, naming criteria.key().","triggerScenarios":"A SelectorCriteria with operator Equals/NotEquals but values() empty/null reaches getSingleValue. Like the field variant, the standard Operator.convert parser rejects empty trailing values, so this guards programmatic/SDK construction of SelectorCriteria.","commonSituations":"An SDK or reactive pipeline builds SelectorCriteria manually with an empty value set; a transformation strips the value before conversion; a custom query builder bug.","solutions":["Always populate values with exactly one element for Equals/NotEquals label criteria.","Use Operator.convert(String) to parse label selector strings, which guarantees a value for '='/'!='.","Add a precondition check: if operator is value-based, assert values is non-empty before calling the converter."],"exampleFix":"// before\nnew SelectorCriteria(\"app\", Operator.Equals, Set.of());\n\n// after\nnew SelectorCriteria(\"app\", Operator.Equals, Set.of(\"halo\"));","handlingStrategy":"validation","validationCode":"if ((criteria.operator() == Operator.Equals || criteria.operator() == Operator.NotEquals)\n    && CollectionUtils.isEmpty(criteria.values())) {\n    throw new IllegalArgumentException(\"Operator \" + criteria.operator()\n        + \" requires a value for label key \" + criteria.key());\n}","typeGuard":"boolean hasValue = !CollectionUtils.isEmpty(criteria.values());","tryCatchPattern":"try {\n    String value = converter.getSingleValue(criteria);\n} catch (IllegalArgumentException e) {\n    // reject the malformed label selector\n}","preventionTips":["Parse label selectors via Operator.convert(String) to guarantee values for =/!=.","When building SelectorCriteria manually, always include exactly one value for value operators.","Add a precondition check in custom selector builders."],"tags":["java","selector","label-selector","validation","query"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}