{"record":{"id":"07607423f9af608b","repo":"flowable/flowable-engine","slug":"exception-during-timer-execution-message-076074","errorCode":null,"errorMessage":"exception during timer execution: ${message}","messagePattern":"exception during timer execution: (.+?)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/jobexecutor/TimerExecuteNestedActivityJobHandler.java","lineNumber":73,"sourceCode":"\n        try {\n            if (commandContext.getEventDispatcher().isEnabled()) {\n                commandContext.getEventDispatcher().dispatchEvent(\n                        ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.TIMER_FIRED, job),\n                        EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);\n                dispatchActivityTimeoutIfNeeded(job, execution, commandContext);\n            }\n\n            borderEventActivity\n                    .getActivityBehavior()\n                    .execute(execution);\n        } catch (RuntimeException e) {\n            LOGGER.error(\"exception during timer execution\", e);\n            throw e;\n\n        } catch (Exception e) {\n            LOGGER.error(\"exception during timer execution\", e);\n            throw new ActivitiException(\"exception during timer execution: \" + e.getMessage(), e);\n        }\n    }\n\n    protected void dispatchActivityTimeoutIfNeeded(Job timerEntity, ExecutionEntity execution, CommandContext commandContext) {\n\n        String nestedActivityId = TimerEventHandler.getActivityIdFromConfiguration(timerEntity.getJobHandlerConfiguration());\n\n        ActivityImpl boundaryEventActivity = execution.getProcessDefinition().findActivity(nestedActivityId);\n        ActivityBehavior boundaryActivityBehavior = boundaryEventActivity.getActivityBehavior();\n        if (boundaryActivityBehavior instanceof BoundaryEventActivityBehavior) {\n            BoundaryEventActivityBehavior boundaryEventActivityBehavior = (BoundaryEventActivityBehavior) boundaryActivityBehavior;\n            if (boundaryEventActivityBehavior.isInterrupting()) {\n                dispatchExecutionTimeOut(timerEntity, execution, commandContext);\n            }\n        }\n    }\n\n    protected void dispatchExecutionTimeOut(Job job, ExecutionEntity execution, CommandContext commandContext) {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/jobexecutor/TimerExecuteNestedActivityJobHandler.java#L55-L91","documentation":"Wrapper thrown when the timer job handler itself throws a checked Exception during execution of the timer's target activity behavior. RuntimeExceptions are rethrown as-is; checked exceptions are wrapped in an ActivitiException with the original message. It indicates the actual timer fire logic (entering the nested activity) failed, e.g. inside a delegate or activity behavior.","triggerScenarios":"Any checked Exception thrown while executing TimerExecuteNestedActivityJobHandler.execute — typically from the activity behavior invoked when the timer fires (TimerCatchIntermediateEventActivityBehavior / boundary event behavior) or from event dispatching code.","commonSituations":"A custom JavaDelegate or listener on the timer target activity throws a checked exception; IO failures during event dispatch; classpath issues loading activity behavior classes in a different deployment context.","solutions":["Read the wrapped cause (e.getCause()) — the root exception identifies the real failure; fix that root cause first","Check the server log for the preceding 'exception during timer execution' LOGGER.error entry with the full stack trace","If caused by a delegate/listener, convert checked exceptions to FlowableException/BpmnError or handle them inside the delegate","After fixing, retry the job via managementService or by resetting retries on the failed job"],"exampleFix":"// before: delegate throws checked exception\npublic void execute(DelegateExecution execution) throws Exception {\n  Files.copy(src, dst); // checked IOException bubbles into ActivitiException\n}\n// after\npublic void execute(DelegateExecution execution) {\n  try { Files.copy(src, dst); }\n  catch (IOException e) { throw new FlowableException(\"copy failed\", e); }\n}","handlingStrategy":"try-catch","validationCode":"// Verify the timer target activity and its delegates are present before firing\nProcessDefinition pd = repositoryService.createProcessDefinitionQuery()\n    .processDefinitionId(defId).singleResult();\nif (pd == null) throw new IllegalStateException(\"definition missing for timer job\");\nBpmnModel model = repositoryService.getBpmnModel(defId);\nif (model.getFlowElement(activityId) == null) throw new IllegalStateException(\"activity \" + activityId + \" missing\");","typeGuard":null,"tryCatchPattern":"try {\n  managementService.executeJob(timerJobId);\n} catch (FlowableException e) {\n  Throwable root = e; while (root.getCause() != null) root = root.getCause();\n  log.error(\"timer execution failed, root cause: {}\", root.getMessage(), root);\n  managementService.setJobRetries(timerJobId, 1); // let it fail definitively after inspection\n}","preventionTips":["Always wrap checked exceptions in delegates/listeners into FlowableException so causes are explicit","Inspect e.getCause() chain, not the wrapper message, when debugging","Keep delegate and listener classes on the async executor's classpath","Set sensible job retry limits so broken timers fail fast instead of looping"],"tags":["job-executor","timer","wrapped-exception"],"backgroundTag":"internal-invariant-violation","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"}