halo-dev/halo · error · IllegalArgumentException

No value present for label key: {}

Error message

No value present for label key: {}

What it means

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

Source

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

                return Queries.labelEqual(criteria.key(), getSingleValue(criteria))
                        .not();
            }
            case NotExist -> {
                return Queries.labelExists(criteria.key()).not();
            }
            case Exist -> {
                return Queries.labelExists(criteria.key());
            }
            case IN -> {
                return Queries.labelIn(criteria.key(), defaultIfNull(criteria.values(), Set.of()));
            }
            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. Always populate values with exactly one element for Equals/NotEquals label criteria.
  2. Use Operator.convert(String) to parse label selector strings, which guarantees a value for '='/'!='.
  3. Add a precondition check: if operator is value-based, assert values is non-empty before calling the converter.

Example fix

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

// after
new SelectorCriteria("app", Operator.Equals, Set.of("halo"));
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 label key " + criteria.key());
}

Type guard

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

Try / catch

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

Prevention

When it happens

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

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

Related errors


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