flowable/flowable-engine · error · IllegalStateException

Unable to find a ProcessEngine service

Error message

Unable to find a ProcessEngine service

What it means

During OSGi bundle processing, Extender.checkBundle waits (up to a configured timeout) for a ProcessEngine to be registered as an OSGi service. If the service tracker times out or returns null, it throws IllegalStateException because deploying the bundle's processes is impossible without an engine. This indicates the Flowable engine was not started or not exported as a service in the OSGi container.

Solutions

  1. Ensure the Flowable ProcessEngine (e.g. flowable-osgi / engine bundle) is started before the process-containing bundle
  2. Check engine startup logs for initialization failure (database, config)
  3. Increase the Extender timeout configuration if the engine starts slowly
  4. Verify the ProcessEngine is registered as an OSGi service with the properties the service tracker filters on

Example fix

// before
// process bundle started while engine bundle still in STARTING
// after
// in the process bundle activator, require the engine first:
ServiceReference<?> ref = context.getServiceReference(ProcessEngine.class);
if (ref == null) { throw new BundleException("ProcessEngine service not available; start the Flowable engine bundle first"); }
Defensive patterns

Strategy: validation

Validate before calling

BundleContext ctx = ...;
ServiceReference<ProcessEngine> ref = ctx.getServiceReference(ProcessEngine.class);
if (ref == null) {
    throw new IllegalStateException("Flowable ProcessEngine OSGi service not registered; start the engine bundle before process bundles");
}

Try / catch

try {
    extenderCheckBundle();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("ProcessEngine")) {
        logger.error("ProcessEngine service unavailable — verify engine bundle is ACTIVE and registered", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A bundle containing BPMN/BAR resources is started (via bundleChanged or at container startup via checkInitialBundle) while no ProcessEngine OSGi service is registered, or the engine registers later than the timeout passed to engineServiceTracker.waitForService(timeout).

Common situations: Flowable engine bundle not started before process bundles; engine failed to initialize (bad database config) so its service never registered; timeout too short for slow container startup; engine registered with wrong service properties so the tracker filter doesn't match.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-osgi/src/main/java/org/flowable/osgi/Extender.java:212

                        filePattern = name;
                    } else {
                        baseName = name.substring(0, pos + 1);
                        filePattern = name.substring(pos + 1);
                    }
                    if (hasWildcards(filePattern)) {
                        addEntries(bundle, baseName, filePattern, pathList);
                    } else {
                        addEntry(bundle, name, pathList);
                    }
                }
            }

            if (!pathList.isEmpty()) {
                LOGGER.debug("Found flowable process in bundle {} with paths: {}", bundle.getSymbolicName(), pathList);

                ProcessEngine engine = (ProcessEngine) engineServiceTracker.waitForService(timeout);
                if (engine == null) {
                    throw new IllegalStateException("Unable to find a ProcessEngine service");
                }

                RepositoryService service = engine.getRepositoryService();
                DeploymentBuilder builder = service.createDeployment();
                builder.name(bundle.getSymbolicName());
                for (URL url : pathList) {
                    InputStream is = url.openStream();
                    if (is == null) {
                        throw new IOException("Error opening url: " + url);
                    }
                    try {
                        builder.addInputStream(getPath(url), is);
                    } finally {
                        is.close();
                    }
                }
                builder.enableDuplicateFiltering();
                builder.deploy();

View on GitHub (pinned to d6d39ce1c6)