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 == null

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Raise WorkflowDef.timeoutSeconds to match the workflow's realistic end-to-end SLA.
  2. Switch timeoutPolicy to ALERT_ONLY if you want notification without termination.
  3. Find the stuck/slow task blocking workflow completion and fix or timeout it individually.
  4. 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

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

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/a8522e6a2626c9e9. Report an issue: GitHub.