flowable/flowable-engine · error · ActivitiException
exception during timer execution: ${message}
Error message
exception during timer execution: ${message} What it means
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.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/jobexecutor/TimerExecuteNestedActivityJobHandler.java:73
try {
if (commandContext.getEventDispatcher().isEnabled()) {
commandContext.getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.TIMER_FIRED, job),
EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);
dispatchActivityTimeoutIfNeeded(job, execution, commandContext);
}
borderEventActivity
.getActivityBehavior()
.execute(execution);
} catch (RuntimeException e) {
LOGGER.error("exception during timer execution", e);
throw e;
} catch (Exception e) {
LOGGER.error("exception during timer execution", e);
throw new ActivitiException("exception during timer execution: " + e.getMessage(), e);
}
}
protected void dispatchActivityTimeoutIfNeeded(Job timerEntity, ExecutionEntity execution, CommandContext commandContext) {
String nestedActivityId = TimerEventHandler.getActivityIdFromConfiguration(timerEntity.getJobHandlerConfiguration());
ActivityImpl boundaryEventActivity = execution.getProcessDefinition().findActivity(nestedActivityId);
ActivityBehavior boundaryActivityBehavior = boundaryEventActivity.getActivityBehavior();
if (boundaryActivityBehavior instanceof BoundaryEventActivityBehavior) {
BoundaryEventActivityBehavior boundaryEventActivityBehavior = (BoundaryEventActivityBehavior) boundaryActivityBehavior;
if (boundaryEventActivityBehavior.isInterrupting()) {
dispatchExecutionTimeOut(timerEntity, execution, commandContext);
}
}
}
protected void dispatchExecutionTimeOut(Job job, ExecutionEntity execution, CommandContext commandContext) {View on GitHub (pinned to d6d39ce1c6)
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
Example fix
// before: delegate throws checked exception
public void execute(DelegateExecution execution) throws Exception {
Files.copy(src, dst); // checked IOException bubbles into ActivitiException
}
// after
public void execute(DelegateExecution execution) {
try { Files.copy(src, dst); }
catch (IOException e) { throw new FlowableException("copy failed", e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the timer target activity and its delegates are present before firing
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(defId).singleResult();
if (pd == null) throw new IllegalStateException("definition missing for timer job");
BpmnModel model = repositoryService.getBpmnModel(defId);
if (model.getFlowElement(activityId) == null) throw new IllegalStateException("activity " + activityId + " missing"); Try / catch
try {
managementService.executeJob(timerJobId);
} catch (FlowableException e) {
Throwable root = e; while (root.getCause() != null) root = root.getCause();
log.error("timer execution failed, root cause: {}", root.getMessage(), root);
managementService.setJobRetries(timerJobId, 1); // let it fail definitively after inspection
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Error reading json value " + configuration + " for job " + j
- exception during timer execution for " + job
- Job ${jobId} failed
- Error while firing timer: border event activity ${nestedActi
- exception during timer execution: ${message}
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/07607423f9af608b.
Report an issue: GitHub.