Skip to content
Latchkey

helmfile "diff ... exited with status 2" in CI

The helm-diff plugin, which helmfile uses for diff and apply, returns exit code 2 when there are changes to apply (like git diff --exit-code). A CI job that treats any non-zero exit as failure will fail on an expected diff.

What this error means

A helmfile diff step in CI stops with "command \"helm\" exited with non-zero status ... exit status 2" even though the diff output looks correct.

helmfile
in ./helmfile.yaml: command "helm" exited with non-zero status:

COMMAND: helm diff upgrade --reset-values --allow-unreleased ...
EXIT STATUS: 2

Common causes

helm-diff signals changes with exit code 2

By design, --detailed-exitcode returns 2 when a diff is non-empty. helmfile propagates that, so the step exits non-zero on any drift.

The pipeline treats a drift signal as an error

A gate meant to detect drift is wired to fail the job on non-zero, conflating "there are changes" with "the command failed".

How to fix it

Interpret exit code 2 as "has changes"

  1. In a drift-detection step, treat exit 2 as changes present, not failure.
  2. Reserve real failure for other non-zero codes.
  3. Fail the job only when you want to block on undeployed drift.
Terminal
helmfile diff
code=$?
if [ "$code" -eq 2 ]; then echo "changes pending"; elif [ "$code" -ne 0 ]; then exit "$code"; fi

Suppress the detailed exit code when you only want output

Pass the helm-diff flag through helmfile so a diff does not set exit code 2.

Terminal
helmfile diff --suppress-secrets --no-color -- --no-detailed-exitcode

How to prevent it

  • Document that helm-diff exit code 2 means "changes present".
  • Use helmfile apply for deploy and diff only for preview gates.
  • Handle exit codes explicitly in drift-detection scripts.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →