quarkusio/quarkus · error · IllegalArgumentException

Key ${key} not found

Error message

Key ${key} not found

What it means

Thrown by ValueRegistryImpl.get when a recorder asks for a RuntimeValue whose RuntimeKey was never registered via register(). During STATIC_INIT, recorders create and register values into the ValueRegistry held by the StartupContext; get() later retrieves them by key. A miss means the producing recorder never ran, ran after the consumer, or the key instance does not match the one used at registration time.

Source

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

        }
        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) {
        return values.containsKey(key.key());
    }

    @SuppressWarnings("unchecked")
    public <T> T get(final RuntimeKey<T> key) {
        RuntimeInfo<T> runtimeInfo = (RuntimeInfo<T>) values.get(key.key());
        if (runtimeInfo == null) {
            throw new IllegalArgumentException("Key " + key.key() + " not found");
        }
        return runtimeInfo.get(this);
    }

    @SuppressWarnings("unchecked")
    public <T> T getOrDefault(final RuntimeKey<T> key, final T defaultValue) {
        RuntimeInfo<T> runtimeInfo = (RuntimeInfo<T>) values.get(key.key());
        return runtimeInfo == null ? defaultValue : runtimeInfo.get(this);
    }

    @Override
    public RuntimeInfo<?> get(final String key) {
        return values.get(key);
    }

    public static Builder builder() {
        return new Builder();
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Use getOrDefault(key, default) instead of get() when absence is acceptable.
  2. Ensure the registering code path actually ran before the lookup (check ordering/startup phases).
  3. Verify the exact same RuntimeKey instance/string is used for register and get.
  4. Check containsKey() first and handle absence explicitly.

Example fix

// before
int size = registry.get(MyKeys.POOL_SIZE); // throws if never registered
// after
int size = registry.getOrDefault(MyKeys.POOL_SIZE, 10);
Defensive patterns

Strategy: fallback

Validate before calling

if (registry.containsKey(key)) {
    value = registry.get(key);
} else {
    value = defaultValue;
}

Type guard

boolean isAvailable(ValueRegistryImpl registry, RuntimeKey<?> key) {
    return key != null && registry.containsKey(key);
}

Try / catch

try {
    value = registry.get(key);
} catch (IllegalArgumentException e) {
    if (e.getMessage().endsWith("not found")) {
        value = defaultValue;
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling get(key) before the corresponding register() ran, with a mistyped key constant, or on a registry instance other than the one that was populated.

Common situations: Ordering problem where consumer code runs before the producer registration; extension removed/renamed so its key is no longer registered; config for a feature disabled so registration was skipped.

Related errors


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