quarkusio/quarkus · error · IllegalArgumentException

Key cannot be null

Error message

Key cannot be null

What it means

Thrown by ValueRegistryImpl.register when a recorder attempts to store a RuntimeValue under a null RuntimeKey. The registry maps RuntimeKey instances to RuntimeInfo entries created by recorders at application startup; a null key has no storage identity, so the registration guard rejects it before the internal map is touched. It indicates a recorder bug (passing an uninitialized key) rather than a user configuration problem.

Source

Thrown at core/runtime/src/main/java/io/quarkus/runtime/ValueRegistryImpl.java:35

 * <p>
 * Each Quarkus application has its own separate instance, created on application start. The {@link ValueRegistry} is
 * then stored in the {@link io.quarkus.runtime.StartupContext} before any recorders are executed, so that it can be
 * 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());
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the RuntimeKey passed to register is non-null and was created with a non-null key string.
  2. Validate keys before registering, or fail earlier at key construction time.
  3. Check the extension recorder that produces the RuntimeKey for a null return value.

Example fix

// before
registry.register(key, value); // key may be null
// after
Objects.requireNonNull(key, "key");
Objects.requireNonNull(key.key(), "key.key()");
registry.register(key, value);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(key, "RuntimeKey must not be null");
Objects.requireNonNull(key.key(), "RuntimeKey.key() must not be null");
registry.register(key, value);

Type guard

boolean validKey(RuntimeKey<?> k) { return k != null && k.key() != null; }

Prevention

When it happens

Trigger: Calling register(null, value) or register(keyWhoseKeyIsNull, value) — typically from extension code building runtime values with a mis-constructed RuntimeKey.

Common situations: Extension code constructing RuntimeKey dynamically where a name/config lookup returned null; refactoring that dropped key initialization.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f99567eedb244c34. Report an issue: GitHub.