flowable/flowable-engine · error · FlowableIllegalArgumentException
deadletterJobId is null
Error message
deadletterJobId is null
What it means
MoveDeadLetterJobToHistoryJobCmd.execute() validates deadletterJobId and throws FlowableIllegalArgumentException when it is null. The command moves a dead-letter job to the history job table, which requires the id of the dead-letter job to move.
Solutions
- Null-check the dead-letter job id before calling moveDeadLetterJobToHistoryJob.
- Re-query the dead-letter job list before each move in loops, since successful moves invalidate stale ids.
- Correct the caller/wrapper that forwards null instead of failing earlier.
Example fix
// before
for (Job job : jobs) {
managementService.moveDeadLetterJobToHistoryJob(job.getId());
}
// after
for (Job job : jobs) {
if (job != null && job.getId() != null) {
managementService.moveDeadLetterJobToHistoryJob(job.getId());
}
} Defensive patterns
Strategy: validation
Validate before calling
if (deadLetterJobId == null || deadLetterJobId.isEmpty()) throw new IllegalArgumentException("deadLetterJobId required"); Type guard
boolean canMove = deadLetterJob != null && deadLetterJob.getId() != null;
Try / catch
try { managementService.moveDeadLetterJobToHistoryJob(id); } catch (FlowableIllegalArgumentException e) { log.warn("Skipped move: {}", e.getMessage()); } Prevention
- Re-query dead-letter jobs between moves; stale ids may be null/gone
- Never pass through optional parameters unchecked
- Log and skip invalid entries in batch jobs
When it happens
Trigger: Calling ManagementService.moveDeadLetterJobToHistoryJob(deadLetterJobId) with a null id, or constructing/executing the command directly without the id.
Common situations: Iterating dead-letter jobs where a prior operation already moved/deleted the job and the stale reference is null; API wrappers forwarding null from optional parameters; copy-paste mistakes where the wrong variable is passed.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5f4a09cb9b30ff52.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/MoveDeadLetterJobToHistoryJobCmd.java:50
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(MoveDeadLetterJobToHistoryJobCmd.class);
protected String deadletterJobId;
protected int retries;
protected JobServiceConfiguration jobServiceConfiguration;
public MoveDeadLetterJobToHistoryJobCmd(String deadletterJobId, int retries, JobServiceConfiguration jobServiceConfiguration) {
this.deadletterJobId = deadletterJobId;
this.retries = retries;
this.jobServiceConfiguration = jobServiceConfiguration;
}
@Override
public HistoryJob execute(CommandContext commandContext) {
if (deadletterJobId == null) {
throw new FlowableIllegalArgumentException("deadletterJobId is null");
}
DeadLetterJobEntity deadLetterJobEntity = jobServiceConfiguration.getDeadLetterJobEntityManager().findById(deadletterJobId);
if (deadLetterJobEntity == null) {
throw new JobNotFoundException(deadletterJobId);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Moving deadletter job to history job table {}", deadLetterJobEntity.getId());
}
return jobServiceConfiguration.getJobManager().moveDeadLetterJobToHistoryJob(deadLetterJobEntity, retries);
}
public String getDeadletterJobId() {
return deadletterJobId;
}
View on GitHub (pinned to d6d39ce1c6)