quarkusio/quarkus · error · IllegalArgumentException

Invalid Flyway callback. It shouldn't be abstract and must h

Error message

Invalid Flyway callback. It shouldn't be abstract and must have a default constructor

What it means

Quarkus discovers Flyway Callback beans by fully-qualified class name from the build-time index. A valid callback class must be concrete and provide a default constructor so it can be instantiated reflectively at deployment; otherwise this IllegalArgumentException is thrown.

Source

Thrown at extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java:90

     * @exception InstantiationException if the {@link Callback} class represents an abstract class.
     * @exception InvocationTargetException if the underlying constructor throws an exception.
     * @exception IllegalAccessException if the {@link Callback} constructor is enforcing Java language access control
     *            and the underlying constructor is inaccessible
     */
    private Collection<Callback> callbacksForDataSource(String dataSourceName)
            throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
        final Optional<List<String>> callbackConfig = flywayBuildConfig.datasources().get(dataSourceName).callbacks();
        if (!callbackConfig.isPresent()) {
            return Collections.emptyList();
        }
        final Collection<String> callbacks = callbackConfig.get();
        final Collection<Callback> instances = new ArrayList<>(callbacks.size());
        for (String callback : callbacks) {
            final ClassInfo clazz = combinedIndexBuildItem.getIndex().getClassByName(DotName.createSimple(callback));
            Objects.requireNonNull(clazz,
                    "Flyway callback not found, please verify the fully qualified name for the class: " + callback);
            if (Modifier.isAbstract(clazz.flags()) || !clazz.hasNoArgsConstructor()) {
                throw new IllegalArgumentException(
                        "Invalid Flyway callback. It shouldn't be abstract and must have a default constructor");
            }
            final Class<?> clazzType = Class.forName(callback, false, Thread.currentThread().getContextClassLoader());
            final Callback instance = (Callback) clazzType.getConstructors()[0].newInstance();
            instances.add(instance);
            reflectiveClassProducer
                    .produce(ReflectiveClassBuildItem.builder(clazz.name().toString()).build());
        }
        return instances;
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the callback class concrete (non-abstract) and add a public no-argument constructor
  2. Point quarkus.flyway.callbacks at a concrete subclass that implements Callback
  3. Verify the fully qualified class name in configuration is correct
  4. If constructor args are needed, provide an additional no-arg constructor or use static/CDI-compatible instantiation

Example fix

// before
public abstract class MyCallback implements Callback { ... }
// after
public class MyCallback implements Callback {
    public MyCallback() { }
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(callbackName);
if (Modifier.isAbstract(c.getModifiers()))
    throw new IllegalStateException(callbackName + " is abstract");
if (Arrays.stream(c.getConstructors()).noneMatch(k -> k.getParameterCount() == 0))
    throw new IllegalStateException(callbackName + " has no default constructor");

Prevention

When it happens

Trigger: quarkus.flyway.<datasource>.callbacks lists a class that is abstract, or has no no-arg constructor; instantiation via getConstructors()[0].newInstance() then fails conceptually at validation time.

Common situations: Registering an abstract base Callback class instead of a concrete subclass; a callback with only parameterized constructors; after refactoring removed the default constructor; typos pointing at the wrong class.

Related errors


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