flowable/flowable-engine · error · FlowableObjectNotFoundException

Timer job with id '' doesn't have an exception stacktrace.

Error message

Timer job with id '' doesn't have an exception stacktrace.

What it means

Thrown by the CMMN REST API when fetching the exception stacktrace of a timer job via GET /cmmn-management/timer-jobs/{jobId}-exception-stacktrace, but the management service returns null — meaning the timer job exists yet has never failed, so no stacktrace is stored. FlowableObjectNotFoundException with String.class signals the requested resource (the stacktrace) does not exist.

Source

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

        }

        response.setContentType("text/plain");
        return stackTrace;
    }

    @ApiOperation(value = "Get the exception stacktrace for a timer job", tags = { "Jobs" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the requested job was not found and the stacktrace has been returned. The response contains the raw stacktrace and always has a Content-type of text/plain."),
            @ApiResponse(code = 404, message = "Indicates the requested job was not found or the job does not have an exception stacktrace. Status-description contains additional information about the error.")
    })
    @GetMapping("/cmmn-management/timer-jobs/{jobId}/exception-stacktrace")
    public String getTimerJobStacktrace(@ApiParam(name = "jobId") @PathVariable String jobId, HttpServletResponse response) {
        Job job = getTimerJobById(jobId);

        String stackTrace = managementService.getTimerJobExceptionStacktrace(job.getId());

        if (stackTrace == null) {
            throw new FlowableObjectNotFoundException("Timer job with id '" + job.getId() + "' doesn't have an exception stacktrace.", String.class);
        }

        response.setContentType("text/plain");
        return stackTrace;
    }

    @ApiOperation(value = "Get the exception stacktrace for a suspended job", tags = { "Jobs" })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the requested job was not found and the stacktrace has been returned. The response contains the raw stacktrace and always has a Content-type of text/plain."),
            @ApiResponse(code = 404, message = "Indicates the requested job was not found or the job does not have an exception stacktrace. Status-description contains additional information about the error.")
    })
    @GetMapping("/cmmn-management/suspended-jobs/{jobId}/exception-stacktrace")
    public String getSuspendedJobStacktrace(@ApiParam(name = "jobId") @PathVariable String jobId, HttpServletResponse response) {
        Job job = getSuspendedJobById(jobId);

        String stackTrace = managementService.getSuspendedJobExceptionStacktrace(job.getId());

        if (stackTrace == null) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Only call the stacktrace endpoint for jobs that have actually failed (check job exception state via the job query first).
  2. Catch FlowableObjectNotFoundException / handle the 404 response as 'no failure yet', not as an error.
  3. Verify the jobId points at a timer job that previously threw (e.g. a stuck deadletter/timer job).

Example fix

// before
String stackTrace = client.getTimerJobStacktrace(jobId);
// after
Job timerJob = managementService.createTimerJobQuery().jobId(jobId).singleResult();
if (timerJob != null && "FAILED".equals(timerJob.getExceptionMessage())) {
    String stackTrace = client.getTimerJobStacktrace(jobId);
}
Defensive patterns

Strategy: try-catch

Validate before calling

Job j = managementService.createTimerJobQuery().jobId(jobId).singleResult();
boolean safe = j != null && j.getExceptionMessage() != null;

Try / catch

try { String s = managementService.getTimerJobExceptionStacktrace(jobId); }
catch (FlowableObjectNotFoundException e) { /* no stacktrace stored — treat as null */ }

Prevention

When it happens

Trigger: GET /cmmn-management/timer-jobs/{jobId}-exception-stacktrace for a timer job whose exceptionStackTrace column is null — i.e. the job has not thrown since creation, or the stacktrace was cleared on retry.

Common situations: Polling the stacktrace endpoint for a healthy timer job; a client assuming every job has a failure record; calling the endpoint right after creating/rescheduling the job.

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/c9adf3b555e29885. Report an issue: GitHub.