flowable/flowable-engine · error · FlowableIllegalArgumentException

processInstanceIds is null

Error message

processInstanceIds is null

What it means

BulkDeleteHistoricProcessInstancesCmd.execute throws FlowableIllegalArgumentException when the collection of process instance ids passed to bulk-delete historic process instances is null. The bulk delete is a single history-recording operation, so it cannot proceed without an explicit id list.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/BulkDeleteHistoricProcessInstancesCmd.java:36

import org.flowable.common.engine.api.FlowableIllegalArgumentException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.CommandContextUtil;

public class BulkDeleteHistoricProcessInstancesCmd implements Command<Object>, Serializable {

    private static final long serialVersionUID = 1L;
    protected Collection<String> processInstanceIds;

    public BulkDeleteHistoricProcessInstancesCmd(Collection<String> processInstanceIds) {
        this.processInstanceIds = processInstanceIds;
    }

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

        if (processInstanceIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("processInstanceIds is empty");
        }
        
        CommandContextUtil.getHistoryManager(commandContext).recordBulkDeleteProcessInstances(processInstanceIds);

        return null;
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Null-check the id collection before invoking the bulk delete and fail fast in your own code with a clear message.
  2. Ensure upstream queries return empty lists instead of null (initialize the list at declaration).
  3. If ids come from configuration/input, validate presence before calling the API.
  4. Wrap the call in try-catch for FlowableIllegalArgumentException only as a last-resort guard, not as control flow.

Example fix

// before
historyService.bulkDeleteHistoricProcessInstances(ids); // ids may be null
// after
if (ids == null) {
    throw new IllegalArgumentException("processInstanceIds must not be null");
}
historyService.bulkDeleteHistoricProcessInstances(ids);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(processInstanceIds, "processInstanceIds must not be null");

Type guard

boolean isUsableIdList(List<String> ids) {
    return ids != null && !ids.isEmpty();
}

Try / catch

try {
    historyService.bulkDeleteHistoricProcessInstances(ids);
} catch (FlowableIllegalArgumentException e) {
    logger.error("Invalid argument for bulk historic delete: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling runtimeService/historyService bulk delete historic process instances API (e.g. managementService or custom code constructing new BulkDeleteHistoricProcessInstancesCmd(null)) with a null List, commonly the result of an earlier query that returned null or an unset method parameter.

Common situations: Code paths where the id list comes from another query or a nullable variable and was never null-checked; Spring beans with optional parameters; refactors where a default empty list was replaced by null.

Related errors


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