{"record":{"id":"c9adf3b555e29885","repo":"flowable/flowable-engine","slug":"timer-job-with-id-doesn-t-have-an-exception-sta","errorCode":null,"errorMessage":"Timer job with id '' doesn't have an exception stacktrace.","messagePattern":"Timer job with id '' doesn't have an exception stacktrace\\.","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobExceptionStacktraceResource.java","lineNumber":69,"sourceCode":"        }\n\n        response.setContentType(\"text/plain\");\n        return stackTrace;\n    }\n\n    @ApiOperation(value = \"Get the exception stacktrace for a timer job\", tags = { \"Jobs\" })\n    @ApiResponses(value = {\n            @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.\"),\n            @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.\")\n    })\n    @GetMapping(\"/cmmn-management/timer-jobs/{jobId}/exception-stacktrace\")\n    public String getTimerJobStacktrace(@ApiParam(name = \"jobId\") @PathVariable String jobId, HttpServletResponse response) {\n        Job job = getTimerJobById(jobId);\n\n        String stackTrace = managementService.getTimerJobExceptionStacktrace(job.getId());\n\n        if (stackTrace == null) {\n            throw new FlowableObjectNotFoundException(\"Timer job with id '\" + job.getId() + \"' doesn't have an exception stacktrace.\", String.class);\n        }\n\n        response.setContentType(\"text/plain\");\n        return stackTrace;\n    }\n\n    @ApiOperation(value = \"Get the exception stacktrace for a suspended job\", tags = { \"Jobs\" })\n    @ApiResponses(value = {\n            @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.\"),\n            @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.\")\n    })\n    @GetMapping(\"/cmmn-management/suspended-jobs/{jobId}/exception-stacktrace\")\n    public String getSuspendedJobStacktrace(@ApiParam(name = \"jobId\") @PathVariable String jobId, HttpServletResponse response) {\n        Job job = getSuspendedJobById(jobId);\n\n        String stackTrace = managementService.getSuspendedJobExceptionStacktrace(job.getId());\n\n        if (stackTrace == null) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobExceptionStacktraceResource.java#L51-L87","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only call the stacktrace endpoint for jobs that have actually failed (check job exception state via the job query first).","Catch FlowableObjectNotFoundException / handle the 404 response as 'no failure yet', not as an error.","Verify the jobId points at a timer job that previously threw (e.g. a stuck deadletter/timer job)."],"exampleFix":"// before\nString stackTrace = client.getTimerJobStacktrace(jobId);\n// after\nJob timerJob = managementService.createTimerJobQuery().jobId(jobId).singleResult();\nif (timerJob != null && \"FAILED\".equals(timerJob.getExceptionMessage())) {\n    String stackTrace = client.getTimerJobStacktrace(jobId);\n}","handlingStrategy":"try-catch","validationCode":"Job j = managementService.createTimerJobQuery().jobId(jobId).singleResult();\nboolean safe = j != null && j.getExceptionMessage() != null;","typeGuard":null,"tryCatchPattern":"try { String s = managementService.getTimerJobExceptionStacktrace(jobId); }\ncatch (FlowableObjectNotFoundException e) { /* no stacktrace stored — treat as null */ }","preventionTips":["Query the job's exception state before requesting the stacktrace","Map 404 on this endpoint to 'no failure yet' in clients","Only monitor stacktraces for jobs known to be failing"],"tags":["flowable","rest-api","job","stacktrace","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}