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

  1. Add a public no-args constructor to the context class
  2. Or change the constructor to accept exactly one io.quarkus.arc.CurrentContextFactory parameter
  3. 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

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


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