flowable/flowable-engine · critical · FlowableException

Could not find an implementation of the org.flowable.cdi.spi

Error message

Could not find an implementation of the org.flowable.cdi.spi.ProcessEngineLookup service returning a non-null processEngine. Giving up.

What it means

During CDI container startup, FlowableExtension.lookupProcessEngine() iterates ProcessEngineLookup service implementations (via META-INF/services) to obtain a ProcessEngine. If no lookup is found — or all return null — it throws FlowableException, aborting initialization. The CDI module cannot function without a process engine.

Source

Thrown at modules/flowable-cdi/src/main/java/org/flowable/cdi/impl/FlowableExtension.java:105

                return (-1) * ((Integer) o1.getPrecedence()).compareTo(o2.getPrecedence());
            }
        });

        ProcessEngine processEngine = null;

        for (ProcessEngineLookup processEngineLookup : discoveredLookups) {
            processEngine = processEngineLookup.getProcessEngine();
            if (processEngine != null) {
                this.processEngineLookup = processEngineLookup;
                LOGGER.debug("ProcessEngineLookup service {} returned process engine.", processEngineLookup.getClass());
                break;
            } else {
                LOGGER.debug("ProcessEngineLookup service {} returned 'null' value.", processEngineLookup.getClass());
            }
        }

        if (processEngineLookup == null) {
            throw new FlowableException("Could not find an implementation of the org.flowable.cdi.spi.ProcessEngineLookup service " + "returning a non-null processEngine. Giving up.");
        }

        FlowableServices services = ProgrammaticBeanLookup.lookup(FlowableServices.class, beanManager);
        services.setProcessEngine(processEngine);

        return processEngine;
    }

    private void deployProcesses(ProcessEngine processEngine) {
        new ProcessDeployer(processEngine).deployProcesses();
    }

    public void beforeShutdown(@Observes BeforeShutdown event) {
        if (processEngineLookup != null) {
            processEngineLookup.ungetProcessEngine();
            processEngineLookup = null;
        }
        LOGGER.info("Shutting down flowable-cdi");

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Create META-INF/services/org.flowable.cdi.spi.ProcessEngineLookup containing your implementation class (e.g. LocalProcessEngineLookup).
  2. Ensure the lookup's getProcessEngine() builds/returns a non-null engine (e.g. a StandaloneProcessEngineConfiguration with H2 datasource).
  3. Verify the implementation class is on the classpath and instantiable (public no-arg constructor).

Example fix

// before
(no services file) -> FlowableException at startup
// after
# file: META-INF/services/org.flowable.cdi.spi.ProcessEngineLookup
org.myapp.MyProcessEngineLookup

public class MyProcessEngineLookup implements ProcessEngineLookup {
  public ProcessEngine getProcessEngine() {
    ProcessEngineConfiguration cfg = ProcessEngineConfiguration
        .createStandaloneProcessEngineConfiguration()
        .setDatabaseSchemaUpdate("true");
    return cfg.buildProcessEngine();
  }
}
Defensive patterns

Strategy: validation

Validate before calling

URL res = getClass().getResource("/META-INF/services/org.flowable.cdi.spi.ProcessEngineLookup");
if (res == null) {
  throw new IllegalStateException("Register a ProcessEngineLookup in META-INF/services");
}

Try / catch

try {
  // deploy/start the CDI app
} catch (FlowableException e) {
  if (e.getMessage().contains("ProcessEngineLookup")) {
    // add/fix the services registration before continuing
  }
}

Prevention

When it happens

Trigger: Deploying an app using flowable-cdi without registering an org.flowable.cdi.spi.ProcessEngineLookup implementation in META-INF/services, or the registered lookup returns null from getProcessEngine().

Common situations: Missing META-INF/services/org.flowable.cdi.spi.ProcessEngineLookup file after a migration to the new ServiceLoader mechanism; the old DefaultProcessEngineLookup/LocalProcessEngineLookup removed from auto-registration; typo in the services file class name.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/7e2c110f78111e79. Report an issue: GitHub.