## TL;DR
"invalid_payload" means the JSON you posted is not a valid Slack message payload: malformed JSON, a wrong top-level structure, or blocks that violate the schema. Validate locally first: parse your own JSON, check it against the message schema, and only then blame the network. Nine times out of ten the bug is in the bytes you sent.

## The query

```text
slack support alert webhook "invalid_payload"
```

## Use this when

- Slack webhooks return invalid_payload
- Alert notifications silently fail
- You are building Slack alert integrations
- Webhooks work in testing but fail in production

## Not for

- Building Slack apps
- Managing Slack channels
- Deciding what to alert on
- Slack workflow builder

## Steps

### 1. Capture and inspect the exact bytes sent

Log the raw request body on failure. "invalid_payload" without the payload is undebuggable. The bytes show the truth: truncated JSON, bad escaping, or a template that rendered empty.

Expected output: the failing payload captured verbatim.

### 2. Validate the JSON parses before blaming Slack

Run the captured body through a JSON parser locally. Unescaped quotes, trailing commas, and encoding issues fail here first. If your own parser rejects it, Slack never stood a chance.

Expected output: locally valid JSON confirmed.

### 3. Check the payload against the message schema

Valid JSON can still be an invalid message: missing text fallback, malformed blocks, attachments in the wrong shape. Validate structure against the schema: top-level fields, block types, required subfields.

Expected output: schema-valid message structure.

### 4. Test with the minimal working payload

Post the simplest possible message (plain text) to the same webhook. If it works, add structure back piece by piece until it breaks. Bisection finds the offending field fast.

Expected output: the specific breaking field identified.

### 5. Pin the payload builder version and test it

Template changes, library upgrades, and "small" refactors silently break payloads. Keep a test that posts a representative alert to a test webhook on every change to the builder. Payload regressions get caught before production.

Expected output: payload builder covered by a posting test.

## Template: the checklist

```text
Slack invalid_payload fix:
[ ] Failing payload captured verbatim
[ ] JSON validity confirmed locally
[ ] Structure validated against the message schema
[ ] Offending field found by bisection from minimal payload
[ ] Builder covered by a posting test
```

## Variant phrasings

### slack webhook invalid payload error

Steps 1 and 2. Capture, parse locally.

### slack alert not posting

Steps 1 and 4. Capture, bisect from minimal.

### incoming webhook payload rejected

Steps 2 and 3. JSON validity plus schema.

## Why it happens

Alert payloads get built by string templating: variables interpolated into JSON by hand, with no validation between the template and the wire. The first unusual value (a quote in a ticket title, an emoji, a null where text was expected) breaks the JSON or the schema. Templating without validation is a bug waiting for interesting data.

## Edge cases

- User-generated content in alerts: ticket titles and customer names contain quotes, newlines, and emoji. Escape or use structured blocks.
- Payload size limits: very long alerts get rejected. Truncate with an explicit marker.
- Webhook URL rotation: a rotated URL fails differently (not invalid_payload). Confirm the error is really the payload.
- Rate limiting: bursts of alerts can 429. invalid_payload is not rate limiting; do not confuse them.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_QBuOVifSqqaNQiHFR3XvLQ
