quarkusio/quarkus · error · IllegalArgumentException

`functionName` must be either `Function<Map<String, Object>,

Error message

`functionName` must be either `Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>>` or `Function<Map<String, Object>, Map.Entry<List<Consumer<BuildChainBuilder>>, List<Consumer<BuildExecutionBuilder>>>>`

What it means

CuratedApplication.createAugmentor looks up a user-supplied augmentor Function class by name (`functionName` system/config property), loads it in the augmentor classloader, and checks whether it implements the accepted generic signatures. If the loaded class is not a Function producing either List<Consumer<BuildChainBuilder>> or Map.Entry<List<Consumer<BuildChainBuilder>>, List<Consumer<BuildExecutionBuilder>>>, it throws this IllegalArgumentException. It is a contract mismatch between the configured augmentor class and the bootstrap API.

Source

Thrown at independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/app/CuratedApplication.java:142

            Class<?> augmentor = getOrCreateAugmentClassLoader().loadClass(AUGMENTOR);
            Function<Object, Object> function = (Function<Object, Object>) getOrCreateAugmentClassLoader()
                    .loadClass(functionName)
                    .getDeclaredConstructor()
                    .newInstance();
            var res = function.apply(props);
            if (res instanceof List l) {
                return (AugmentAction) augmentor.getConstructor(CuratedApplication.class, List.class, List.class)
                        .newInstance(this, l, Collections.emptyList());
            } else if (res instanceof Map.Entry e) {
                var key = e.getKey();
                var value = e.getValue();
                if ((key instanceof List l1) && (value instanceof List l2)) {
                    return (AugmentAction) augmentor
                            .getConstructor(CuratedApplication.class, List.class, List.class, List.class)
                            .newInstance(this, l1, l2, Collections.emptyList());
                }
            }
            throw new IllegalArgumentException(
                    "`functionName` must be either `Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>>` or `Function<Map<String, Object>, Map.Entry<List<Consumer<BuildChainBuilder>>, List<Consumer<BuildExecutionBuilder>>>>`");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    private Object runInCl(String consumerName, Map<String, Object> params, QuarkusClassLoader cl) {
        ClassLoader old = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(cl);
            Class<? extends BiConsumer<CuratedApplication, Map<String, Object>>> clazz = (Class<? extends BiConsumer<CuratedApplication, Map<String, Object>>>) cl
                    .loadClass(consumerName);
            BiConsumer<CuratedApplication, Map<String, Object>> biConsumer = clazz.getDeclaredConstructor().newInstance();
            biConsumer.accept(this, params);
            return biConsumer;
        } catch (RuntimeException e) {
            throw e;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the augmentor class implement `Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>>` (or the Map.Entry variant including build-execution consumers).
  2. Check the value configured for the augmentor function name property and correct any typo or stale fully-qualified class name.
  3. Rebuild against the Quarkus version in use; older augmentor signatures were removed and must be migrated.
  4. If you only need a custom augmentor, prefer the standard QuarkusBootstrap.builder().build().createAugmentor() default instead of a custom functionName.

Example fix

// before
public class MyAugmentor implements Function<Map<String, Object>, String> { ... }
// after
public class MyAugmentor implements Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>> {
    public List<Consumer<BuildChainBuilder>> apply(Map<String, Object> params) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(functionClassName);
if (!java.util.function.Function.class.isAssignableFrom(c)) {
    throw new IllegalArgumentException(functionClassName + " must implement Function<Map<String,Object>, ...>");
}

Try / catch

try { app.createAugmentor(); } catch (IllegalArgumentException e) { log.error("Augmentor function signature invalid: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Setting a `functionName`-style property (e.g. via app builder AugmentAction configuration used by app/initAugmentAction/handleDevServices callers) to a class that is not a Function with one of the two required signatures, or one whose type parameters were erased/mismatched so the reflective type check in createAugmentor fails.

Common situations: Custom tooling or dev-services integration registering an augmentor class that implements the wrong interface (e.g. BiFunction or old Quarkus augmentor API), pointing at a stale class from an older Quarkus version, or a typo causing the wrong class to be loaded.

Related errors


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