Slack incoming webhook "no_service" error in CI
Slack returns no_service when it receives a POST to an incoming webhook URL it no longer recognizes. The webhook was deleted, the app was removed from the workspace, or the URL in your secret is wrong. Slack cannot map the request to a channel, so nothing is posted.
What this error means
A build-status notify step posts to the Slack webhook and the response body is the literal string no_service with HTTP 404. The step may still exit 0 if you do not check the body, so notifications silently stop arriving.
< HTTP/2 404
no_serviceCommon causes
The webhook URL was revoked or the app was removed
Incoming webhook URLs are tied to a specific app install. If the app is uninstalled or the webhook is regenerated, the old URL returns no_service for every request.
The secret holds a stale or truncated URL
A SLACK_WEBHOOK_URL secret copied incorrectly, or one that lost its trailing path segment, no longer resolves to a live webhook.
How to fix it
Regenerate the webhook and update the secret
- Open the Slack app config, go to Incoming Webhooks, and confirm the webhook still exists for the target channel.
- If it was removed, add a new incoming webhook and copy the full URL including the three path segments after /services/.
- Update the
SLACK_WEBHOOK_URLrepository or organization secret with the new value.
curl -sS -X POST -H 'Content-type: application/json' \
--data '{"text":"build passed"}' \
"$SLACK_WEBHOOK_URL"Fail the step when Slack does not return ok
Check the HTTP status or body so a broken webhook fails loudly instead of dropping notifications silently.
- name: Notify Slack
run: |
code=$(curl -s -o /tmp/r -w '%{http_code}' -X POST \
-H 'Content-type: application/json' \
--data '{"text":"build passed"}' "$SLACK_WEBHOOK_URL")
[ "$code" = "200" ] || { cat /tmp/r; exit 1; }
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}How to prevent it
- Store the webhook only in CI secrets and rotate it in one place when it changes.
- Assert the HTTP status of the notify request so a dead webhook fails the step.
- Document which Slack app owns the webhook so a reinstall does not orphan it.