Skip to content
Latchkey

Slack incoming webhook "invalid_payload" error in CI

Slack returns invalid_payload with HTTP 400 when the body sent to an incoming webhook is not valid JSON or has no usable message field. In CI this almost always comes from a commit message or branch name interpolated into the JSON without escaping, which breaks the quoting.

What this error means

The notify step posts to the Slack webhook and gets HTTP 400 with the body invalid_payload. It often starts failing only for commits whose messages contain quotes, newlines, or backslashes.

Slack response
< HTTP/2 400
invalid_payload

Common causes

Unescaped values break the JSON

A commit message or PR title with a double quote, newline, or backslash is pasted directly into the {"text":"..."} body, producing invalid JSON that Slack refuses.

Missing text or blocks field

A legacy incoming webhook needs a top-level text (or blocks). Sending an empty object or only unknown keys yields invalid_payload.

How to fix it

Build the JSON with a tool that escapes

  1. Never string-concatenate untrusted text into JSON.
  2. Use jq or a scripting step to encode the message safely.
  3. Pass the result as the request body.
Terminal
msg="$(git log -1 --pretty=%s)"
payload=$(jq -n --arg t "build passed: $msg" '{text:$t}')
curl -sS -X POST -H 'Content-type: application/json' \
  --data "$payload" "$SLACK_WEBHOOK_URL"

Always include a text field

Ensure the payload has a non-empty text even when you also send blocks, so older webhooks accept it.

JSON
{"text":"CI result","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"build passed"}}]}

How to prevent it

  • Encode all interpolated CI values (commit, branch, actor) with jq before sending.
  • Include a fallback text field alongside any blocks.
  • Test the notify step against a real commit message containing a quote.

Frequently asked questions

What causes "Slack "invalid_payload""?
A commit message or PR title with a double quote, newline, or backslash is pasted directly into the {"text":"..."} body, producing invalid JSON that Slack refuses.
How do I fix Slack "invalid_payload"?
Build the JSON with a tool that escapes

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card