quarkusio/quarkus · error · IllegalArgumentException
A context class must either declare a no-args constructor or
Error message
A context class must either declare a no-args constructor or a constructor that accepts a single parameter of type io.quarkus.arc.CurrentContextFactory
What it means
Arc requires every custom context registered via ContextConfigurator.contextClass() to be instantiable from generated bytecode: it must have either a public no-arg constructor or one accepting a single io.quarkus.arc.CurrentContextFactory. If getConstructor() finds neither, an IllegalArgumentException is thrown at registration time.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextConfigurator.java:121
* @return self
*/
public ContextConfigurator normal(boolean value) {
this.isNormal = value;
return this;
}
public ContextConfigurator contextClass(Class<? extends InjectableContext> contextClazz) {
if (!Modifier.isPublic(contextClazz.getModifiers())
|| Modifier.isAbstract(contextClazz.getModifiers())
|| contextClazz.isAnonymousClass()
|| contextClazz.isLocalClass()
|| (contextClazz.getEnclosingClass() != null && !Modifier.isStatic(contextClazz.getModifiers()))) {
throw new IllegalArgumentException(
"A context class must be a public non-abstract top-level or static nested class");
}
Constructor<?> constructor = getConstructor(contextClazz);
if (constructor == null) {
throw new IllegalArgumentException(
"A context class must either declare a no-args constructor or a constructor that accepts a single parameter of type io.quarkus.arc.CurrentContextFactory");
}
return creator(cg -> {
BlockCreator bc = cg.method();
List<Expr> args = constructor.getParameterCount() == 0 ? List.of() : List.of(cg.currentContextFactory());
return bc.new_(ConstructorDesc.of(constructor), args);
});
}
private Constructor<?> getConstructor(Class<? extends InjectableContext> contextClazz) {
Constructor<?> constructor = null;
try {
constructor = contextClazz.getDeclaredConstructor(CurrentContextFactory.class);
} catch (NoSuchMethodException ignored) {
}
if (constructor == null) {
try {View on GitHub (pinned to e1c734241f)
Solutions
- Add a public no-args constructor to the context class
- Or change the constructor to accept exactly one io.quarkus.arc.CurrentContextFactory parameter
- If construction needs extra state, obtain it inside the context via the CurrentContextFactory or static config instead of constructor params
Example fix
// before
public MyContext(String name) { ... }
// after
public MyContext() { ... }
// or
public MyContext(io.quarkus.arc.CurrentContextFactory f) { ... } Defensive patterns
Strategy: validation
Validate before calling
static void validateContextCtor(Class<? extends InjectableContext> c) {
boolean ok = false;
for (Constructor<?> k : c.getConstructors()) {
if (k.getParameterCount() == 0) ok = true;
if (k.getParameterCount() == 1 && k.getParameterTypes()[0] == io.quarkus.arc.CurrentContextFactory.class) ok = true;
}
if (!ok) throw new IllegalArgumentException("No valid constructor on " + c);
} Type guard
static boolean hasValidContextConstructor(Class<?> c) {
return java.util.Arrays.stream(c.getConstructors()).anyMatch(k ->
k.getParameterCount() == 0
|| (k.getParameterCount() == 1 && k.getParameterTypes()[0] == io.quarkus.arc.CurrentContextFactory.class));
} Prevention
- Provide a public no-arg constructor on every custom context
- Use CurrentContextFactory parameter when you need contextual state storage
When it happens
Trigger: Registering a context class whose constructors take other parameter types (e.g. a String config argument) or whose no-arg constructor is private/not public.
Common situations: Porting a CDI context from another container that allowed constructor injection; making constructors package-private; adding a config parameter to the constructor after upgrading.
Related errors
- A context class must be a public non-abstract top-level or s
- Multiple @Inject constructors on ${theClass}
- Quarkus does not support CDI Full @Specializes annotation; t
- IllegalStateException wrapping ClassNotFoundException for ge
- Unable to derive the logger name at ${injectionPoint}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/a3428a732edd78fa.
Report an issue: GitHub.