quarkusio/quarkus · error · IllegalArgumentException
Value cannot be null
Error message
Value cannot be null
What it means
ValueRegistryImpl.register() validates its arguments before inserting into the backing ConcurrentHashMap. It throws IllegalArgumentException('Value cannot be null') when the value being registered is null. The registry refuses null values because a null entry would be indistinguishable from a missing key during lookup.
Source
Thrown at core/runtime/src/main/java/io/quarkus/runtime/ValueRegistryImpl.java:38
* injected into the recorders' constructors as a {@link RuntimeValue}.
*
* @see Application#Application(boolean)
* @see "io.quarkus.deployment.steps.MainClassBuildStep#build for storage"
* @see "io.quarkus.deployment.ExtensionLoader#loadStepsFrom for retrieval"
* @see "io.quarkus.deployment.recording.ObjectLoader"
*/
public class ValueRegistryImpl implements ValueRegistry {
private final Map<String, RuntimeInfo<?>> values = new ConcurrentHashMap<>();
private ValueRegistryImpl() {
}
public <T> void register(final RuntimeKey<T> key, final T value) {
if (key == null || key.key() == null) {
throw new IllegalArgumentException("Key cannot be null");
}
if (value == null) {
throw new IllegalArgumentException("Value cannot be null");
}
registerInfo(key, SimpleRuntimeInfo.of(value));
}
public <T> void registerInfo(final RuntimeKey<T> key, final RuntimeInfo<T> runtimeInfo) {
if (key == null || key.key() == null) {
throw new IllegalArgumentException("Key cannot be null");
}
if (runtimeInfo == null) {
throw new IllegalArgumentException("Value cannot be null");
}
RuntimeInfo<?> mapValue = values.putIfAbsent(key.key(), runtimeInfo);
if (mapValue != null) {
throw new IllegalArgumentException("Key already registered " + key.key());
}
}
public <T> boolean containsKey(final RuntimeKey<T> key) {View on GitHub (pinned to e1c734241f)
Solutions
- Check the value for null before calling register(); skip registration or throw a descriptive error naming the source of the null.
- Fix the producing code so it never returns null (substitute a default or Optional-handling).
- Use getOrDefault-style access patterns instead of registering sentinel nulls.
Example fix
// before registry.register(MyKeys.TIMEOUT, config.timeout()); // config.timeout() may be null // after Objects.requireNonNull(config.timeout(), "timeout config missing"); registry.register(MyKeys.TIMEOUT, config.timeout());
Defensive patterns
Strategy: validation
Validate before calling
if (value == null) { throw new IllegalStateException("Refusing to register null value for " + key.key()); }
registry.register(key, value); Type guard
boolean isRegistrable(Object key, Object value) {
return key != null && key.key() != null && value != null;
} Try / catch
try {
registry.register(key, value);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Value cannot be null")) {
log.warnf("Skipping null value for key %s", key.key());
} else { throw e; }
} Prevention
- Apply Objects.requireNonNull on values at their production site
- Never register optional config values without a default
- Wrap registration in a helper that logs and skips nulls
When it happens
Trigger: Calling RuntimeValueRegistry.register(key, null), or registerInfo with a RuntimeInfo that wraps/exposes a null value path via SimpleRuntimeInfo.of(null).
Common situations: A config value or programmatically produced bean resolves to null at startup (e.g. an optional property not set) and the code registers it unconditionally; a factory method returns null instead of throwing.
Related errors
- Key cannot be null
- Key already registered ${key}
- The `mails` parameter must not be `null`
- `timeout` must not be `null`
- `timestamp` must not be `null`
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/88cff0b149f4cafc.
Report an issue: GitHub.