quarkusio/quarkus · error · IllegalArgumentException

A context class must be a public non-abstract top-level or s

Error message

A context class must be a public non-abstract top-level or static nested class

What it means

When registering a custom CDI context programmatically via ContextConfigurator.contextClass(), Arc validates the class is public, non-abstract, not anonymous/local, and if nested, static. Illegal shapes would make instantiating the context in generated bytecode impossible, so an IllegalArgumentException is thrown at registration time.

Source

Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ContextConfigurator.java:116

     * By default, the context is considered normal if the scope annotion is annotated with {@link NormalScope}.
     * <p>
     * It is possible to change this behavior. However, in such case the registrator is responsible for the correct
     * implementation of {@link InjectableContext#isNormal()}.
     *
     * @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 {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the context class public
  2. Remove abstract modifier or subclass it concretely
  3. Mark the nested class static (or move it to top level)
  4. Ensure it is a named class, not anonymous/local

Example fix

// before
public class App { class MyContext extends RequestContext {} }
// after
public class App { public static class MyContext extends RequestContext {} }
Defensive patterns

Strategy: validation

Validate before calling

static void validateContextClass(Class<? extends InjectableContext> c) {
  int m = c.getModifiers();
  if (!Modifier.isPublic(m) || Modifier.isAbstract(m) || c.isAnonymousClass() || c.isLocalClass()
      || (c.getEnclosingClass() != null && !Modifier.isStatic(m)))
    throw new IllegalArgumentException("Invalid context class: " + c);
}

Type guard

static boolean isValidContextClass(Class<?> c) {
  int m = c.getModifiers();
  return Modifier.isPublic(m) && !Modifier.isAbstract(m) && !c.isAnonymousClass()
      && !c.isLocalClass() && (c.getEnclosingClass() == null || Modifier.isStatic(m));
}

Prevention

When it happens

Trigger: Calling ArCContexts/register API with a context class that is package-private, abstract, an inner (non-static) class, an anonymous class, or a local class.

Common situations: Declaring the custom context as a non-static inner class of the test or application class; making the context package-private for 'encapsulation'; using a lambda-style anonymous subclass.

Related errors


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