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
- Use getOrDefault(key, default) instead of get() when absence is acceptable.
- Ensure the registering code path actually ran before the lookup (check ordering/startup phases).
- Verify the exact same RuntimeKey instance/string is used for register and get.
- 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
- Use getOrDefault whenever absence is acceptable
- Verify registration ordering (producer before consumer)
- Share the same registry instance and identical RuntimeKey constants
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
- Key cannot be null
- Value cannot be null
- Key already registered ${key}
- Failed to initialize Quarkus extension catalog resolver
- Malformed URL: + url
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ab663ff52751bd94.
Report an issue: GitHub.