flowable/flowable-engine · error · FlowableIllegalArgumentException
historyJobId is null
Error message
historyJobId is null
What it means
ExecuteHistoryJobCmd throws FlowableIllegalArgumentException when historyJobId is null, then looks up the history job and throws JobNotFoundException if absent. History jobs handle async history persistence, and execution is impossible without a valid id.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/ExecuteHistoryJobCmd.java:47
* @author Joram Barrez
*/
public class ExecuteHistoryJobCmd implements Command<Void> {
private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteHistoryJobCmd.class);
protected JobServiceConfiguration jobServiceConfiguration;
protected String historyJobId;
public ExecuteHistoryJobCmd(String historyJobId, JobServiceConfiguration jobServiceConfiguration) {
this.historyJobId = historyJobId;
this.jobServiceConfiguration = jobServiceConfiguration;
}
@Override
public Void execute(CommandContext commandContext) {
if (historyJobId == null) {
throw new FlowableIllegalArgumentException("historyJobId is null");
}
HistoryJobEntity historyJobEntity = jobServiceConfiguration.getHistoryJobEntityManager().findById(historyJobId);
if (historyJobEntity == null) {
throw new JobNotFoundException(historyJobId);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Executing historyJob {}", historyJobEntity.getId());
}
try {
jobServiceConfiguration.getJobManager().execute(historyJobEntity);
} catch (Throwable exception) {
// Finally, Throw the exception to indicate the failure
throw new FlowableException(historyJobEntity + " failed", exception);
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the history job id is populated before executing the command.
- Check that the history job producer (async history) writes a non-null id into the queued message.
- In custom history handlers, guard against null ids and skip/log instead of executing.
- Confirm the entity manager can find the id in ACT_RU_HISTORY_JOB before executing.
Example fix
// before
commandExecutor.execute(new ExecuteHistoryJobCmd(historyJobId, cfg)); // null id
// after
if (historyJobId == null) {
LOGGER.warn("Skipping history job execution: null id");
return;
}
commandExecutor.execute(new ExecuteHistoryJobCmd(historyJobId, cfg)); Defensive patterns
Strategy: validation
Validate before calling
if (historyJobId == null) { LOGGER.warn("Skip: null history job id"); return; } Try / catch
try { commandExecutor.execute(new ExecuteHistoryJobCmd(historyJobId, cfg)); } catch (FlowableIllegalArgumentException | JobNotFoundException e) { LOGGER.warn("History job not executable: {}", e.getMessage()); } Prevention
- Ensure async history producers serialize a non-null job id.
- Guard custom history handlers against null ids and skip with a warning.
- Test history job round-trips after Flowable upgrades.
When it happens
Trigger: Executing new ExecuteHistoryJobCmd(null, cfg); history job handlers invoked with a null id after a fetch produced nothing; JobServiceConfiguration.getExecuteHistoryJobCmd supplied a null id.
Common situations: Custom async history handlers where the job id was lost during serialization into the history job queue; tests calling the command directly; misconfigured history job handler factories.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d3a78232867717bb.
Report an issue: GitHub.