flowable/flowable-engine · info · FlowableObjectNotFoundException

Job with id '${jobId}' does not have an exception stacktrace

Error message

Job with id '${jobId}' does not have an exception stacktrace.

What it means

getJobStacktrace fetches a job and then its stored exception stacktrace; when managementService.getJobExceptionStacktrace returns null (the job exists but never failed, so no stacktrace was recorded), a FlowableObjectNotFoundException (String.class) is thrown.

Source

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

 * @author Joram Barrez
 */
@RestController
@Api(tags = { "Jobs" }, authorizations = { @Authorization(value = "basicAuth") })
public class JobExceptionStacktraceResource extends JobBaseResource {

    @ApiOperation(value = "Get the exception stacktrace for a 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("/management/jobs/{jobId}/exception-stacktrace")
    public String getJobStacktrace(@ApiParam(name = "jobId") @PathVariable String jobId, HttpServletResponse response) {
        Job job = getJobById(jobId);

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

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

        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("/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) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Only request the stacktrace for jobs whose retries were decremented / that are in failed state.
  2. Treat a 404 here as 'no failure recorded yet' rather than a missing job.
  3. Check the job's exception message first via the job resource before fetching the stacktrace.
  4. Wait for the next failure if the job is expected to fail but has not executed yet.

Example fix

// before
curl http://localhost:8080/flowable-rest/management/jobs/7/exception-stacktrace  // 404
// after: verify the job actually failed first
curl http://localhost:8080/flowable-rest/management/jobs/7 | jq '.exceptionMessage'
# only fetch stacktrace when exceptionMessage is non-null
Defensive patterns

Strategy: try-catch

Validate before calling

const job = await fetch(`${base}/management/jobs/${jobId}`).then(r => r.json());
if (!job.exceptionMessage) return null; // no stacktrace exists yet

Type guard

function hasRecordedFailure(job) { return !!job && typeof job.exceptionMessage === 'string' && job.exceptionMessage.length > 0; }

Try / catch

try {
  const trace = await getJobStacktrace(jobId);
} catch (e) {
  if (e.status === 404) return null; // job has no failure recorded
  throw e;
}

Prevention

When it happens

Trigger: GET /management/jobs/{jobId}/exception-stacktrace for a job that has not yet thrown an exception (e.g. a healthy waiting timer or a freshly created job).

Common situations: Monitoring scripts that poll stacktraces for every job, jobs retried successfully so the stacktrace column was cleared, or fetching before the first failed execution.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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