Unknown blocks and fallbacks

Rendering is tolerant of JSON-compatible runtime data and does not run strict validation first. Slack can add block types before the package knows their shape; an unknown discriminator renders as a labeled fallback instead of being silently omitted.

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
    }
  ]
}

Fallback behavior is not limited to whole blocks. This payload clamps an out-of-range header level, shows an image placeholder for a slack_file ID without a URL, renders a zero-total pie state, leaves an unresolved mention and unknown emoji readable, and shows a labeled fallback for an invented accessory inside an otherwise usable 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
Known block or element with unusable required fieldsUsable siblings remain; the malformed part becomes a fallback or empty preview
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
Image with a missing, unusable, or non-HTTP(S) sourceNamed placeholder; a valid URL that fails during browser loading remains a failed <img>
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

Passing a string that fails JSON.parse throws BlockKitInvariantError with code: "invalid_json". Strict validators throw the same error class for invalid payloads; rendering itself does not call them.

Resolver and onAction functions are host application code. The renderer does not catch their errors or convert them to BlockKitInvariantError. Resolver failures occur while React renders; onAction failures occur in React event handlers and are reported according to the host's event-error handling. Catch failures in the callback when the application needs controlled recovery.

When you want strictness

Tolerant rendering shows the payload as-is. For the package's strict 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 the package's strict limits (block counts, text lengths, element placement, nesting), which the renderer deliberately does not. The full rule inventory and the message-input compatibility caveat are in the validation reference.