Skip to main content
In this lesson we demonstrate an Argo Workflows exit handler using a compact example. Exit handlers run once at the end of a workflow regardless of success or failure and are ideal for cleanup, notifications, or posting results to external systems. This behavior is analogous to Jenkins pipelines’ post { always { ... } } block. Below is a minimal workflow that shows an onExit handler named cleanup. The primary work deliberately fails (exit code 1) so you can verify the exit handler still executes.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  name: exit-handler-workflow
  namespace: argo
spec:
  entrypoint: main
  onExit: cleanup # Always runs this template at the end
  templates:
  - name: main
    steps:
    - - name: work
        template: do-work
  - name: do-work
    container:
      image: alpine
      command: [sh, -c]
      args: ["echo 'Doing work...'; exit 1"] # This fails intentionally
  - name: cleanup
    container:
      image: alpine
      command: [sh, -c]
      args:
      - |
        echo "Workflow status: {{workflow.status}}"
        echo "Cleaning up resources..."
        if [ "{{workflow.status}}" = "Failed" ]; then
          echo "Sending failure notification"
        fi
Use onExit to centralize cleanup and notification logic. Inspect {{workflow.status}} to run conditional actions (for example, send alerts on Failure or perform extra validation on Succeeded).

What each template does

TemplatePurposeExample behavior
entrypoint (main)Starting point of the workflowExecutes the do-work step
do-workPrimary task/containerPrints a message and intentionally exits 1 to simulate failure
cleanupExit handler invoked via onExitPrints workflow status and conditionally sends a failure notification
Explanation:
  • entrypoint: main — workflow starts at the main template.
  • onExit: cleanup — ensures the cleanup template runs when the workflow finishes, irrespective of success or failure.
  • do-work — the container task that demonstrates a failing step.
  • cleanup — exit handler that reads {{workflow.status}} and conditionally performs actions.

Viewing results

Even when a step fails, the exit handler still runs. In the Argo UI you can see the failed work step and the exit-handler node (typically displayed in green to indicate it completed). The screenshot below shows the failed work step and the exit-handler node along with pod details.
A screenshot of the Argo Workflows web UI showing a vertical workflow graph with a red failed "work" step and a green exit-handler node. The right-hand summary panel lists pod details including a "Failed" phase and an error message with an exit code.
Sample cleanup logs printed after the workflow fails:
Workflow status: Failed
Cleaning up resources...
Sending failure notification
You can replace the echo commands with real integrations: Slack notifications, posting status to a webhook, cleaning up cloud resources, or triggering recovery workflows. When designing critical cleanup actions, make them idempotent so repeated runs are safe.
Although onExit executes in normal success and failure scenarios, extreme outages (for example: controller crashes, severe cluster failures, or lost persistence) may prevent the exit handler from running. For critical cleanup, combine onExit with idempotent design or external watchdog processes.

Practical tips

  • Test exit handlers by forcing failures (exit codes) or injecting errors to ensure notifications and cleanups behave as expected.
  • Use {{workflow.status}}, {{workflow.name}}, and other workflow variables to include contextual details in alerts.
  • Keep exit handlers small and focused; offload heavy or long-running recovery tasks to separate workflows or jobs to avoid unexpected interactions.

References

Watch Video