Notification step misconfigured with if: failure() never runs in CI
A notify step guarded by if: failure() only runs when a previous step in the same job failed. If the job is cancelled, times out, or the failure happens in a different job, the condition is false and no alert is sent. Use if: always() (or if: failure() scoped correctly) so notifications fire when you expect.
What this error means
Builds fail but no Slack, Discord, Teams, email, SMS, or PagerDuty alert arrives. The notify step shows as skipped in the run summary rather than failed.
Notify Slack
This step was skipped because the job condition was not met.Common causes
if: failure() does not cover cancellations or other jobs
failure() is true only when a prior step in the same job failed. A cancelled or timed-out run, or a failure in a separate job, leaves it false, so the step is skipped.
A success-only condition skips on failure
A notify step with no condition (implicit success()) is skipped as soon as any earlier step fails, so failure alerts never send.
How to fix it
Run the notify step with if: always()
- Use
if: always()so the step runs regardless of prior outcome. - Inside it, branch on
job.statusorneeds.*.resultto pick the message. - For cross-job alerts, put the notify in a job that
needsthe others and usesif: always().
- name: Notify
if: always()
run: ./scripts/notify.sh "${{ job.status }}"Alert from a dependent job
A final job that needs the others can report the aggregate result even when a matrix leg failed or was cancelled.
notify:
needs: [build, test]
if: always()
runs-on: ubuntu-latest
steps:
- run: ./scripts/notify.sh "${{ needs.test.result }}"How to prevent it
- Use
if: always()on notify steps and branch on status inside. - Centralize alerting in a dependent job that needs the others.
- Test the failure path so you confirm alerts actually fire.