flowable/flowable-engine · critical · ActivitiException

invalid command interceptor chain configuration

Error message

invalid command interceptor chain configuration: ${chain}

What it means

initInterceptorChain links the configured CommandInterceptor list into a chain and returns its head. If the list is null or empty there is no first interceptor, so the engine cannot build a CommandExecutor and throws this ActivitiException. This indicates the interceptor configuration was not initialized correctly.

Solutions

  1. Ensure defaultCommandInterceptors is populated before initCommandExecutors runs (call the default init methods in your subclass)
  2. Do not return an empty list from custom pre/post interceptor configuration — add at least the standard chain (log, transaction, command context interceptors)
  3. If subclassing, override initInterceptorChain only to extend, never to replace with an empty chain

Example fix

// before
@Override
protected List<CommandInterceptor> getDefaultCommandInterceptors() {
  return customInterceptors; // may be empty
}
// after
@Override
protected List<CommandInterceptor> getDefaultCommandInterceptors() {
  List<CommandInterceptor> list = super.getDefaultCommandInterceptors();
  list.addAll(customInterceptors);
  return list;
}
Defensive patterns

Strategy: validation

Validate before calling

List<CommandInterceptor> chain = cfg.getDefaultCommandInterceptors();
if (chain == null || chain.isEmpty()) {
  throw new IllegalStateException("Command interceptor chain must not be empty");
}

Try / catch

try {
  processEngine = cfg.buildProcessEngine();
} catch (ActivitiException e) {
  if (e.getMessage().startsWith("invalid command interceptor chain")) {
    throw new ConfigurationException("Populate defaultCommandInterceptors before building the engine", e);
  } else throw e;
}

Prevention

When it happens

Trigger: Custom process engine configuration that overrides/clears defaultCommandInterceptors or customPreCommandInterceptors/customPostCommandInterceptors such that resolveInterceptors produces an empty list passed to initInterceptorChain during engine init.

Common situations: Subclassing ProcessEngineConfigurationImpl and forgetting to call super or to populate defaultCommandInterceptors; filtering logic removing all interceptors; misconfigured custom interceptor lists.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java:688

        CommandInterceptor transactionInterceptor = createTransactionInterceptor();
        if (transactionInterceptor != null) {
            interceptors.add(transactionInterceptor);
        }

        interceptors.add(new CommandContextInterceptor(commandContextFactory, this));
        return interceptors;
    }

    protected void initCommandExecutor() {
        if (commandExecutor == null) {
            CommandInterceptor first = initInterceptorChain(commandInterceptors);
            commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);
        }
    }

    protected CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) {
        if (chain == null || chain.isEmpty()) {
            throw new ActivitiException("invalid command interceptor chain configuration: " + chain);
        }
        for (int i = 0; i < chain.size() - 1; i++) {
            chain.get(i).setNext(chain.get(i + 1));
        }
        return chain.get(0);
    }

    protected abstract CommandInterceptor createTransactionInterceptor();

    // services /////////////////////////////////////////////////////////////////

    protected void initServices() {
        initService(repositoryService);
        initService(runtimeService);
        initService(historyService);
        initService(identityService);
        initService(taskService);
        initService(formService);

View on GitHub (pinned to d6d39ce1c6)