halo-dev/halo · error · IllegalArgumentException

No value present for label key: {}

Error message

No value present for label key: {}

What it means

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().

Source

Thrown at api/src/main/java/run/halo/app/extension/router/selector/FieldSelectorConverter.java:38

        switch (criteria.operator()) {
            case Equals -> {
                return Queries.equal(key, getSingleValue(criteria));
            }
            case NotEquals -> {
                return Queries.notEqual(key, getSingleValue(criteria));
            }
            // compatible with old field selector
            case IN -> {
                Set<String> valueArr = defaultIfNull(criteria.values(), Set.of());
                return Queries.in(key, valueArr);
            }
            default -> throw new IllegalArgumentException("Unsupported operator: " + criteria.operator());
        }
    }

    String getSingleValue(SelectorCriteria criteria) {
        if (CollectionUtils.isEmpty(criteria.values())) {
            throw new IllegalArgumentException("No value present for label key: " + criteria.key());
        }
        return criteria.values().iterator().next();
    }
}

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. When constructing SelectorCriteria for Equals/NotEquals, always pass a non-empty Set with exactly one value.
  2. Prefer the Operator.convert(String) parser for user input, which guarantees a value for '='/'!='.
  3. Guard programmatically: assert criteria.values() is non-empty before invoking the converter for value operators.

Example fix

// before
new SelectorCriteria("status", Operator.Equals, Set.of());

// after
new SelectorCriteria("status", Operator.Equals, Set.of("active"));
Defensive patterns

Strategy: validation

Validate before calling

if ((criteria.operator() == Operator.Equals || criteria.operator() == Operator.NotEquals)
    && CollectionUtils.isEmpty(criteria.values())) {
    throw new IllegalArgumentException("Operator " + criteria.operator()
        + " requires a value for key " + criteria.key());
}

Type guard

boolean hasValue = !CollectionUtils.isEmpty(criteria.values());

Try / catch

try {
    String value = converter.getSingleValue(criteria);
} catch (IllegalArgumentException e) {
    // supply a default or reject the malformed selector
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/4bf8d7a9259bee3c. Report an issue: GitHub.