{"record":{"id":"f7fd120ae7485686","repo":"quarkusio/quarkus","slug":"invalid-flyway-callback-it-shouldn-t-be-abstract","errorCode":null,"errorMessage":"Invalid Flyway callback. It shouldn't be abstract and must have a default constructor","messagePattern":"Invalid Flyway callback\\. It shouldn't be abstract and must have a default constructor","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java","lineNumber":90,"sourceCode":"     * @exception InstantiationException if the {@link Callback} class represents an abstract class.\n     * @exception InvocationTargetException if the underlying constructor throws an exception.\n     * @exception IllegalAccessException if the {@link Callback} constructor is enforcing Java language access control\n     *            and the underlying constructor is inaccessible\n     */\n    private Collection<Callback> callbacksForDataSource(String dataSourceName)\n            throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {\n        final Optional<List<String>> callbackConfig = flywayBuildConfig.datasources().get(dataSourceName).callbacks();\n        if (!callbackConfig.isPresent()) {\n            return Collections.emptyList();\n        }\n        final Collection<String> callbacks = callbackConfig.get();\n        final Collection<Callback> instances = new ArrayList<>(callbacks.size());\n        for (String callback : callbacks) {\n            final ClassInfo clazz = combinedIndexBuildItem.getIndex().getClassByName(DotName.createSimple(callback));\n            Objects.requireNonNull(clazz,\n                    \"Flyway callback not found, please verify the fully qualified name for the class: \" + callback);\n            if (Modifier.isAbstract(clazz.flags()) || !clazz.hasNoArgsConstructor()) {\n                throw new IllegalArgumentException(\n                        \"Invalid Flyway callback. It shouldn't be abstract and must have a default constructor\");\n            }\n            final Class<?> clazzType = Class.forName(callback, false, Thread.currentThread().getContextClassLoader());\n            final Callback instance = (Callback) clazzType.getConstructors()[0].newInstance();\n            instances.add(instance);\n            reflectiveClassProducer\n                    .produce(ReflectiveClassBuildItem.builder(clazz.name().toString()).build());\n        }\n        return instances;\n    }\n}\n","sourceCodeStart":72,"sourceCodeEnd":102,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/deployment/FlywayCallbacksLocator.java#L72-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the callback class concrete (non-abstract) and add a public no-argument constructor","Point quarkus.flyway.callbacks at a concrete subclass that implements Callback","Verify the fully qualified class name in configuration is correct","If constructor args are needed, provide an additional no-arg constructor or use static/CDI-compatible instantiation"],"exampleFix":"// before\npublic abstract class MyCallback implements Callback { ... }\n// after\npublic class MyCallback implements Callback {\n    public MyCallback() { }\n    ...\n}","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(callbackName);\nif (Modifier.isAbstract(c.getModifiers()))\n    throw new IllegalStateException(callbackName + \" is abstract\");\nif (Arrays.stream(c.getConstructors()).noneMatch(k -> k.getParameterCount() == 0))\n    throw new IllegalStateException(callbackName + \" has no default constructor\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register only concrete classes with public no-arg constructors in quarkus.flyway.callbacks","Double-check fully qualified class names in config","Add a startup test that instantiates each configured callback"],"tags":["flyway","callback","build-time","reflection"],"backgroundTag":"invalid-callback-class","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}