{"record":{"id":"4bf8d7a9259bee3c","repo":"halo-dev/halo","slug":"no-value-present-for-label-key","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/FieldSelectorConverter.java","lineNumber":38,"sourceCode":"        switch (criteria.operator()) {\n            case Equals -> {\n                return Queries.equal(key, getSingleValue(criteria));\n            }\n            case NotEquals -> {\n                return Queries.notEqual(key, getSingleValue(criteria));\n            }\n            // compatible with old field selector\n            case IN -> {\n                Set<String> valueArr = defaultIfNull(criteria.values(), Set.of());\n                return Queries.in(key, valueArr);\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/FieldSelectorConverter.java#L20-L43","documentation":"Thrown by FieldSelectorConverter.getSingleValue when an Equals or NotEquals SelectorCriteria has an empty/null values collection. Equals and NotEquals require exactly one value to build an equality query; with no value the converter cannot form the condition and throws, naming criteria.key().","triggerScenarios":"A SelectorCriteria with operator Equals/NotEquals but values() empty or null reaches getSingleValue — typically only possible when building SelectorCriteria programmatically (the standard Operator parser rejects key= with an empty trailing value, so this guards internal/SDK construction).","commonSituations":"An SDK or extension builds SelectorCriteria manually and forgets to populate values; a mapping layer drops the value; an edge-case input that bypasses Operator.convert.","solutions":["When constructing SelectorCriteria for Equals/NotEquals, always pass a non-empty Set with exactly one value.","Prefer the Operator.convert(String) parser for user input, which guarantees a value for '='/'!='.","Guard programmatically: assert criteria.values() is non-empty before invoking the converter for value operators."],"exampleFix":"// before\nnew SelectorCriteria(\"status\", Operator.Equals, Set.of());\n\n// after\nnew SelectorCriteria(\"status\", Operator.Equals, Set.of(\"active\"));","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 key \" + criteria.key());\n}","typeGuard":"boolean hasValue = !CollectionUtils.isEmpty(criteria.values());","tryCatchPattern":"try {\n    String value = converter.getSingleValue(criteria);\n} catch (IllegalArgumentException e) {\n    // supply a default or reject the malformed selector\n}","preventionTips":["Build SelectorCriteria via Operator.convert(String) so value operators always carry a value.","When constructing manually, always pass a single-element Set for Equals/NotEquals.","Unit-test selector construction to assert non-empty values for value operators."],"tags":["java","selector","field-selector","validation","query"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}