flowable/flowable-engine · error · FlowableIllegalArgumentException

processDefinitionId is null

Error message

processDefinitionId is null

What it means

GetProcessDefinitionInfoCmd's sibling for history levels: execute throws FlowableIllegalArgumentException('processDefinitionId is null') when the constructor argument is null. The command resolves the history level defined in a process definition's model, which requires an id. Fail-fast argument validation before any lookup.

Solutions

  1. Guard the id before invoking and throw/return with a clear message
  2. Ensure the variable is populated from processEngineConfiguration or a deployment result before use
  3. Check the upstream lookup (definition query) that produced the null id
  4. Add an assertion/unit test covering the null-id path

Example fix

// before
HistoryLevel level = engineConfig.getHistoryLevel(processDefinitionId); // id may be null
// after
if (processDefinitionId == null) {
    throw new IllegalArgumentException("Cannot resolve history level: processDefinitionId is null");
}
HistoryLevel level = engineConfig.getHistoryLevel(processDefinitionId);
Defensive patterns

Strategy: validation

Validate before calling

if (processDefinitionId == null) {
  throw new IllegalStateException("processDefinitionId must be resolved before reading history level");
}

Try / catch

try {
  HistoryLevel level = getHistoryLevelForProcessDefinition(defId);
} catch (FlowableIllegalArgumentException e) {
  level = defaultHistoryLevel;
}

Prevention

When it happens

Trigger: Invoking the dynamic history-level lookup (e.g. via process engine configuration's getHistoryLevel(processDefinitionId)) with a null id — usually an unset variable or a lookup chain that returned null upstream.

Common situations: Configuration code that resolves the definition id conditionally and proceeds even when resolution failed; refactored code paths where the id assignment was removed; programmatic engine bootstrapping passing null defaults.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/GetProcessDefinitionHistoryLevelModelCmd.java:45

import org.flowable.engine.repository.ProcessDefinition;

/**
 * @author Tijs Rademakers
 */
public class GetProcessDefinitionHistoryLevelModelCmd implements Command<HistoryLevel>, Serializable {

    private static final long serialVersionUID = 1L;

    protected String processDefinitionId;

    public GetProcessDefinitionHistoryLevelModelCmd(String processDefinitionId) {
        this.processDefinitionId = processDefinitionId;
    }

    @Override
    public HistoryLevel execute(CommandContext commandContext) {
        if (processDefinitionId == null) {
            throw new FlowableIllegalArgumentException("processDefinitionId is null");
        }

        HistoryLevel historyLevel = null;

        ProcessDefinition processDefinition = CommandContextUtil.getProcessDefinitionEntityManager(commandContext).findById(processDefinitionId);

        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);

        Process process = bpmnModel.getProcessById(processDefinition.getKey());
        if (process.getExtensionElements().containsKey("historyLevel")) {
            ExtensionElement historyLevelElement = process.getExtensionElements().get("historyLevel").iterator().next();
            String historyLevelValue = historyLevelElement.getElementText();
            if (StringUtils.isNotEmpty(historyLevelValue)) {
                try {
                    historyLevel = HistoryLevel.getHistoryLevelForKey(historyLevelValue);

                } catch (Exception e) {
                }

View on GitHub (pinned to d6d39ce1c6)