flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a dead letter job with id '${jobId}'.

Error message

Could not find a dead letter job with id '${jobId}'.

What it means

Moving a deadletter job back to the executable queue failed because the job id does not exist. The REST layer re-throws FlowableObjectNotFoundException with the standard deadletter message for consistency.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobResource.java:327

                restApiInterceptor.moveDeadLetterJob(deadLetterJob, MOVE_ACTION);
            }
            /*
             * Note that the jobType is checked to know which kind of move that needs to be done.
             * The MOVE_TO_HISTORY_JOB_ACTION allows to specifically force the move to a history job and trigger the else part below.
             */

            try {
                if (HistoryJobEntity.HISTORY_JOB_TYPE.equals(deadLetterJob.getJobType())) {
                    managementService.moveDeadLetterJobToHistoryJob(deadLetterJob.getId(), cmmnEngineConfiguration.getAsyncExecutorNumberOfRetries());

                } else {
                    managementService.moveDeadLetterJobToExecutableJob(deadLetterJob.getId(), cmmnEngineConfiguration.getAsyncExecutorNumberOfRetries());

                }

            } catch (FlowableObjectNotFoundException e) {
                // Re-throw to have consistent error-messaging across REST-API
                throw new FlowableObjectNotFoundException("Could not find a dead letter job with id '" + jobId + "'.", Job.class);
            }

        } else if (MOVE_TO_HISTORY_JOB_ACTION.equals(actionRequest.getAction())) {
            if (restApiInterceptor != null) {
                restApiInterceptor.moveDeadLetterJob(deadLetterJob, MOVE_TO_HISTORY_JOB_ACTION);
            }
            try {
                managementService.moveDeadLetterJobToHistoryJob(deadLetterJob.getId(), cmmnEngineConfiguration.getAsyncHistoryExecutorNumberOfRetries());
            } catch (FlowableObjectNotFoundException e) {
                // Re-throw to have consistent error-messaging across REST-api
                throw new FlowableObjectNotFoundException("Could not find a dead letter job with id '" + jobId + "'.", Job.class);
            }

        }

    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Re-list deadletter jobs to confirm the id is still present
  2. Handle 404 gracefully — the job may already have been moved
  3. Verify you are pointing at the correct CMMN engine configuration
Defensive patterns

Strategy: try-catch

Validate before calling

const job = await get(`/cmmn-management/deadletter-jobs/${jobId}`);
if (!job) throw new Error(`deadletter job ${jobId} not found`);

Try / catch

try { await moveDeadLetterJob(jobId); }
catch (e) { if (e.status === 404 && /dead letter job/.test(e.message)) { /* idempotent skip: already moved */ } else throw e; }

Prevention

When it happens

Trigger: POST /cmmn-management/deadletter-jobs/{jobId} with action 'move' where the deadletter job with that id is gone (already moved/retried) or never existed.

Common situations: Double-execution of a move script, id sourced from a different job table (timer/history), wrong engine database.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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