flowable/flowable-engine · error · FlowableIllegalArgumentException

jobId is null

Error message

jobId is null

What it means

Thrown by DeleteDeadLetterJobCmd.getJobToDelete() (via jobToDelete) when deadLetterJobId is null. Deleting a dead letter job requires a concrete id to look up the entity; a null id is rejected up front as FlowableIllegalArgumentException instead of attempting a pointless findById(null).

Solutions

  1. Ensure the dead letter job id is set/non-null before calling the delete API
  2. Filter null entries out of id lists before issuing per-id deletes
  3. At the API boundary, validate the id and return a client error instead of invoking the service

Example fix

// before
managementService.deleteDeadLetterJob(deadLetterJobId); // null
// after
if (deadLetterJobId != null) {
    managementService.deleteDeadLetterJob(deadLetterJobId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (deadLetterJobId == null) {
    throw new IllegalArgumentException("deadLetterJobId is required to delete a dead letter job");
}

Type guard

boolean hasJobId(String id) { return id != null && !id.trim().isEmpty(); }

Try / catch

try {
    managementService.deleteDeadLetterJob(deadLetterJobId);
} catch (FlowableIllegalArgumentException e) {
    LOGGER.error("Delete rejected: {}", e.getMessage());
}

Prevention

When it happens

Trigger: managementService.deleteDeadLetterJob(null) or the builder-based delete called without setting the job id; id variable that was never assigned because a prior query/lookup returned nothing; REST/DTO binding leaving the id field null.

Common situations: Cleanup scripts iterating a list where some entries are null; frontend sending a delete request with a missing id; copy-pasted delete code using the wrong (unset) variable.

Related errors


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

Appendix: source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteDeadLetterJobCmd.java:68

        DeadLetterJobEntity jobToDelete = getJobToDelete(commandContext);

        sendCancelEvent(jobToDelete);

        jobServiceConfiguration.getDeadLetterJobEntityManager().delete(jobToDelete);
        return null;
    }

    protected void sendCancelEvent(DeadLetterJobEntity jobToDelete) {
        FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();
        if (eventDispatcher != null && eventDispatcher.isEnabled()) {
            eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.JOB_CANCELED, jobToDelete),
                    jobServiceConfiguration.getEngineName());
        }
    }

    protected DeadLetterJobEntity getJobToDelete(CommandContext commandContext) {
        if (deadLetterJobId == null) {
            throw new FlowableIllegalArgumentException("jobId is null");
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Deleting job {}", deadLetterJobId);
        }

        DeadLetterJobEntity job = jobServiceConfiguration.getDeadLetterJobEntityManager().findById(deadLetterJobId);
        if (job == null) {
            throw new FlowableObjectNotFoundException("No dead letter job found with id '" + deadLetterJobId + "'", Job.class);
        }

        return job;
    }

}

View on GitHub (pinned to d6d39ce1c6)