conductor-oss/conductor · error · TerminateWorkflowException
Workflow timed out after %d seconds. Timeout configured as %
Error message
Workflow timed out after %d seconds. Timeout configured as %d seconds. Timeout policy configured to %s
What it means
checkWorkflowTimeout fires when elapsed time since create/lastRetry exceeds WorkflowDef.timeoutSeconds and the timeoutPolicy is TIME_OUT_WF. The engine throws a TerminateWorkflowException with status TIMED_OUT, terminating the whole workflow. With ALERT_ONLY the same condition only logs and records a metric.
Source
Thrown at core/src/main/java/com/netflix/conductor/core/execution/DeciderService.java:766
String reason =
String.format(
"Workflow timed out after %d seconds. Timeout configured as %d seconds. "
+ "Timeout policy configured to %s",
elapsedTime / 1000L,
workflowDef.getTimeoutSeconds(),
workflowDef.getTimeoutPolicy().name());
switch (workflowDef.getTimeoutPolicy()) {
case ALERT_ONLY:
LOGGER.info("{} {}", workflow.getWorkflowId(), reason);
Monitors.recordWorkflowTermination(
workflow.getWorkflowName(),
WorkflowModel.Status.TIMED_OUT,
workflow.getOwnerApp());
return;
case TIME_OUT_WF:
throw new TerminateWorkflowException(reason, WorkflowModel.Status.TIMED_OUT);
}
}
/**
* Enforces {@link TaskDef#getTotalTimeoutSeconds()} — a hard wall-clock budget that spans the
* entire lifetime of the task including all retry delays, not just a single attempt.
*
* <p>When the budget is exceeded the task is timed out via the same {@link
* #timeoutTaskWithTimeoutPolicy} path used for per-attempt timeouts, so the configured {@link
* TaskDef.TimeoutPolicy} still applies (ALERT_ONLY logs, RETRY sets TIMED_OUT which then fails
* permanently in {@link #retry}, TIME_OUT_WF terminates the workflow).
*
* <p>Tasks created before {@code firstScheduledTime} was introduced (value == 0) are skipped to
* preserve backward compatibility.
*/
@VisibleForTesting
void checkTotalTimeout(TaskDef taskDef, TaskModel task) {
if (taskDef == nullView on GitHub (pinned to cf7c3e4a8a)
Solutions
- Raise WorkflowDef.timeoutSeconds to match the workflow's realistic end-to-end SLA.
- Switch timeoutPolicy to ALERT_ONLY if you want notification without termination.
- Find the stuck/slow task blocking workflow completion and fix or timeout it individually.
- Verify lastRetriedTime/createTime are set correctly (a rerun resets the clock).
Defensive patterns
Strategy: validation
Validate before calling
// Validate the workflow timeout fits realistic duration before registering.
if (def.getTimeoutSeconds() > 0 && def.getTimeoutSeconds() < minExpectedDurationSeconds(def)) {
LOGGER.warn("WorkflowDef {} timeoutSeconds={} may be too low", def.getName(), def.getTimeoutSeconds());
} Try / catch
try {
deciderService.decide(workflow);
} catch (TerminateWorkflowException e) {
if (e.getStatus() == WorkflowModel.Status.TIMED_OUT) {
// consider ALERT_ONLY policy or raise timeoutSeconds
}
} Prevention
- Set timeoutSeconds from measured end-to-end duration, not a guess.
- Use ALERT_ONLY if you want notification without termination.
- Find and fix stuck tasks that block completion.
When it happens
Trigger: A workflow whose WorkflowDef.timeoutSeconds > 0 and timeoutPolicy=TIME_OUT_WF runs longer than the configured budget (elapsed = now - lastRetriedTime, or now - createTime).
Common situations: Long-running workflow whose steps collectively exceed timeoutSeconds; a stuck task blocking completion; timeoutSeconds set too low for the workflow's real duration.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Task timed out after %d seconds. Timeout configured as %d se
- Task %s failed with status: %s and reason: '%s'
- Task %s/%s exceeded total timeout of %d seconds (elapsed %d
- %s
- No tasks found to be executed
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/a8522e6a2626c9e9.
Report an issue: GitHub.