Unknown blocks and fallbacks

Rendering is total for block-shaped JSON: every entry in the payload produces visible output. Slack ships new block types regularly, and payloads retrieved from the API can contain shapes the renderer has never seen. Those render as a labeled, bounded fallback instead of crashing the tree or disappearing silently.

The next block type does not exist yet:
Unsupported Slack block: meeting_recap
View payload JSON
{
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "The next block type does not exist yet:"
      }
    },
    {
      "type": "meeting_recap",
      "summary": "Q3 planning sync",
      "attendees": 14
    }
  ]
}

Degradation is not only about whole blocks. This payload clamps an out-of-range header level, hits a slack_file image with no fetchable URL, renders a zero-total pie, leaves an unresolved mention and an unknown emoji visible, and drops an invented accessory inside an otherwise fine section:

Clamped to h4

Nothing to plot

none
Unresolved: @U9999999999 :not-a-real-emoji:
Unsupported Block Kit element: hologram_projector
View payload JSON
{
  "blocks": [
    {
      "type": "header",
      "text": {
        "type": "plain_text",
        "text": "Clamped to h4"
      },
      "level": 9
    },
    {
      "type": "image",
      "alt_text": "quarterly chart",
      "slack_file": {
        "id": "F0123456789"
      }
    },
    {
      "type": "data_visualization",
      "title": "Nothing to plot",
      "chart": {
        "type": "pie",
        "segments": [
          {
            "label": "none",
            "value": 0
          }
        ]
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "Unresolved: <@U9999999999> :not-a-real-emoji:"
      },
      "accessory": {
        "type": "hologram_projector",
        "action_id": "beam"
      }
    }
  ]
}

The fallback keeps a human-readable label in the DOM, tagged with data-unhandled-block and data-block-type attributes so you can detect or style degraded content:

document.querySelectorAll("[data-unhandled-block]");

Fallbacks below the block level carry their own attributes: data-unhandled-element (elements and accessories), data-unhandled-rich-text-container and data-unhandled-rich-text-element (rich text), and data-unhandled-chart-type (charts).

What degrades, and how

InputBehavior
Unknown block typeLabeled fallback node with data-block-type
Unknown element or accessory inside a known blockThe block renders; the element becomes a labeled fallback
Unknown rich-text container or inline elementVisible text/reference fallback inside the rich text
Out-of-range presentation values (e.g. header.level: 9)Clamped to the legal range
image with a slack_file IDAlt-labeled placeholder, because a file ID has no renderable URL
Unresolved mentions and custom emojiID or :shortcode: stays visible (see Resolvers)
Empty collections (no rows, no chart data)Render safely; a zero-total pie chart shows a labeled "No chart data" state

What throws

Only non-JSON input: passing a string that fails JSON.parse throws BlockKitInvariantError with code: "invalid_json". The never-throw guarantee starts once the input is valid JSON.

When you want strictness

Tolerant rendering shows the payload as-is. For Slack acceptance checks, run the validators before rendering:

import { parseBlockKitData } from "react-blockkit";

const json = '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"hi"}}]}';
const typed = parseBlockKitData(json, "message");

Validation enforces Slack's documented limits (block counts, text lengths, element placement, nesting), which the renderer deliberately does not. The full rule inventory is in the validation reference.