Slack error invalid_blocks_format: blocks is not a valid JSON array
Last verified against Slack API reference - chat.postMessage errors
The blocks is not a valid JSON object or doesn't match the Block Kit syntax.What error invalid_blocks_format means
Slack could not even parse your blocks value as Block Kit JSON. The documented description: "The blocks is not a valid JSON object or doesn't match the Block Kit syntax." Where invalid_blocks means well-formed JSON broke a content rule, invalid_blocks_format fails one step earlier: the value was not a well-formed array of block objects at all.
The classic cause is double serialization. When you POST with Content-Type: application/json, blocks must be a real JSON array in the body — but code ported from the form-encoded style (where blocks is sent as a JSON string field) often calls JSON.stringify on the array first, producing a quoted string where an array belongs. The reverse happens too: form-encoded requests that send an unquoted structure. Other shapes: a single block object not wrapped in an array, trailing commas from hand-built strings, or a templating engine emitting invalid JSON when a value contains quotes.
The fix is mechanical once seen: send an actual array of objects in JSON bodies, a serialized string only in form-encoded bodies, and let an SDK handle it if possible — the official SDKs serialize correctly and make this error nearly impossible to produce.
What it looks like
// wrong: double-serialized inside a JSON body
{"channel": "C0123ABCDEF", "blocks": "[{\"type\":\"section\"}]"}
HTTP 200
{"ok": false, "error": "invalid_blocks_format"}Why it happens
- The blocks array was JSON.stringify-ed inside an application/json body, arriving as a string instead of an array.
- Hand-assembled JSON with syntax errors: trailing commas, unescaped quotes from interpolated content.
- A single block object sent without the surrounding array.
- Form-encoded requests sending a raw structure where a serialized JSON string is expected.
How to fix Slack error invalid_blocks_format
- 1Log the exact request body bytes; look for \"blocks\": \"[{...}]\" (a quoted string) versus \"blocks\": [{...}] (an array).
- 2In JSON bodies, pass the array directly; remove any pre-serialization step.
- 3In form-encoded bodies, send blocks as a URL-encoded JSON string.
- 4Prefer the official SDK client, which owns serialization; validate remaining hand-built payloads with a JSON linter before sending.
How to stop it recurring
Never build Block Kit JSON by string concatenation; construct native structures and serialize exactly once at the transport boundary. A contract test that posts one minimal block through your real serialization path catches this class of bug on every refactor of the HTTP layer.
Official reference: Slack API reference - chat.postMessage errors. See all Slack error codes or the Slack limits and quotas.
Related codes
Error invalid_blocks_format - quick answers
What does Slack error invalid_blocks_format mean?
Slack could not even parse your blocks value as Block Kit JSON. The documented description: "The blocks is not a valid JSON object or doesn't match the Block Kit syntax." Where invalid_blocks means well-formed JSON broke a content rule, invalid_blocks_format fails one step earlier: the value was not a well-formed array of block objects at all. The classic cause is double serialization .
How do I fix Slack error invalid_blocks_format?
1. Log the exact request body bytes; look for \"blocks\": \"[{...}]\" (a quoted string) versus \"blocks\": [{...}] (an array). 2. In JSON bodies, pass the array directly; remove any pre-serialization step. 3. In form-encoded bodies, send blocks as a URL-encoded JSON string. 4. Prefer the official SDK client, which owns serialization; validate remaining hand-built payloads with a JSON linter before sending.
Should I retry after error invalid_blocks_format?
No. Retrying the same request produces the same error; the condition has to be fixed first. Treat it as a permanent failure for that message and surface it, rather than looping.
Stop debugging Slack by hand
Connect the channel through Conferbot: tokens, webhooks and retries are handled, failures show as readable status.