> ## Documentation Index
> Fetch the complete documentation index at: https://developers.reintersect.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits

> Hard limits on block trees, text lengths, actions, manifests, references and hosted apps, and the messages the validator reports.

> Reintersect apps are in developer preview. Names and limits can still change before general
> release.

Reintersect validates every tree before storing it. A tree over any limit is rejected: the block keeps
its previous tree, and the action or insert that produced it fails. `reintersect check` renders every
block with generated props, and the [testing kit](/testing) checks every tree your tests render. Both
run the same validator Reintersect runs, signed in or not, so they report a broken tree before you
deploy.

## Block trees

| Limit | Value |
| - | - |
| Components per block, not counting plain text | 250 |
| Nesting depth | 12 |
| Serialized tree size | 64 KB |
| Text in one component | 2,000 characters |
| Text in one `Prose` | 10,000 characters |
| Total text in a block | 20,000 characters |
| `summary` | Plain text with visible characters, at most 280 |
| Root `Actions` per block | 1, the last part of the body |
| Buttons in one `Actions` | 5, plus one `Menu` at the end |
| Buttons and menus in one `Row` | 3, after one or two `Text` or `AvatarStack` |
| Items in one `Menu` | 12 |
| Values in one `choice` input | 20 |
| Images per block | 10 |
| Columns in `Columns` | 2 or 3 |
| Tabs in `Tabs` | 2 to 6, never nested |
| Metrics in one `Metrics` | 1 to 6 |
| Items in one `MetaList` | 1 to 6 |
| `Section` depth | One: a section can't hold another section |
| List depth in `Prose` | 2 levels |
| `Table` | 12 columns, 200 rows, 280 characters per text cell, 12 menu items per row |
| `Chart` | 3 series of up to 24 points; a donut has one series of up to 5 points and a total above zero |
| `Metric` trend | 2 to 24 points |
| `AvatarStack` | 50 people |
| Static `Select` options | 100 |
| `TextInput` `maxLength` | 2,000 |
| `audience={{ members }}` | 50 members |
| URLs in a tree | `https://` only, at most 2,048 characters |
| `audience` | One level: never inside another `audience`, and never inside a `Form` (put it on the `Form`). On a `Button` or `Menu` only inside the root `Actions` |
| Input and field names | Unique across the block, including across forms |
| Shared `ChoiceGroup`, `Select` or `Toggle` outside a form | Must have `onChange` |

## Text lengths

Lengths count characters the way people see them, so an emoji or a letter with accents counts as
one. Every label needs visible text: a label made only of spaces or invisible characters is
rejected.

| Text | At most |
| - | - |
| `Header` title, `Item` title | 80 |
| `Header` trailing text, `Item` trailing text | 24 |
| `Item` description | 280 |
| `MetaItem` | 60 |
| `Fact` value | 120 |
| `Text` in a `Footer` | 120 |
| `Button`, `Menu` and `MenuItem` labels, `Form` `submitLabel`, `Tab` labels | 32 |
| `Badge`, `Status` and `Icon` labels, `Fact` and `Metric` labels, status and badge cells | 32 |
| `Table` column labels, `Chart` series names and point labels | 24 |
| `Section` and `Tabs` titles, field labels, choice and option labels, placeholders, `Progress` and `AvatarStack` labels, `Quote` `by`, link cell labels | 60 |
| Person names | 64 |
| `Callout`, `Chart`, `Table` and confirm titles, `Step` labels | 80 |
| `File` names | 120 |
| `Image` `alt` | 200 |
| `Step`, choice and `Toggle` descriptions, confirm `body` | 280 |
| `unit` | 12 |
| Copy text and `TextInput` values | 2,000 |

Labels that must be unique: buttons and the menu label in one `Actions` or `Row`, items in a `Menu`,
tabs in a `Tabs`, choices in a `ChoiceGroup`, options in a `Select`, facts in a `Facts`, metrics in a
`Metrics`, columns in a `Table`, series in a `Chart`, and points in one series. Uniqueness ignores
case and extra spaces.

## What the validator reports

`reintersect check`, the testing kit and Reintersect's server report a broken tree with one of these
messages. Words in braces are filled in with the component as you wrote it, such as `<Tabs>`. The
check and the kit add where the problem is, such as `(in the second <Section>, at content[0].content[0])`.

| Problem | Message |
| - | - |
| A root child out of order, such as a second root `Actions` | `Blocks go header, body, actions, footer: <Block> can't hold {component} here` |
| A child a container doesn't take | `{parent} can't hold {child} here` or `{parent} needs ...` |
| A section inside a section | `<Section> can't hold <Section> here`, or `Sections sit only at block, tab or form level, one deep` when it's nested deeper |
| Tabs inside tabs | `Tabs cannot be nested` |
| A form inside a form | `Forms cannot be nested` |
| A form's last row holds more than its submit | `A form ends with one submit button and nothing else` |
| A submit button outside a form's last row | `Submit buttons belong in a form's last row` |
| A text or date field outside a form | `{component} belongs inside a <Form>` |
| A table, chart or prose in a column | `{component} needs the full width; move it out of the <Column>` |
| A stack inside a stack | `Stacks cannot hold another stack` |
| A collapsed section nobody can open | `A collapsed section needs a title or a toggle button` |
| A toggle button for a missing section | `No section has the handle {handle}` |
| A label used twice | `"{label}" is used twice in this {group}; labels must be unique`, where the group is the component that holds the labels, such as `<Actions>` |
| A label with no visible text | `Labels need visible text` |
| A code block with no text | `Code blocks need visible text` |
| Text over its length | `Keep this to {max} characters or fewer` |
| Prose nested too deeply | `Lists nest at most 2 levels`, `Quotes cannot hold quotes` or `Headings and code blocks can't sit in a list or quote` |
| Struck text with a link | `Struck text can't be a link` |
| A link in a linked header's title | `A linked header's title can't hold links` |
| A link in a linked item's title | `A linked item's title can't hold links` |
| A shared field outside a form without `onChange` | `A shared {component} outside a <Form> needs onChange` |
| An audience inside another audience | `{component} sits inside another audience; audiences can't nest` |
| An audience inside a form | `{component} sits inside a <Form>; put the audience on the <Form>` |
| An audience on a part that can't take one | `{component} can't carry an audience here; move it onto the enclosing {parent}` or `{component} can't carry an audience; set it on a flow element instead` |
| Formatting a container doesn't allow, or the same mark twice | `{component} has formatting that's repeated or not allowed inside {parent}` |
| A hand-built tree with an empty text node | `Text can't be empty` or `Text can't have attrs or content` |
| A count over its limit | Such as `Tabs hold 2 to 6 tabs`, `Metrics hold at most 6 metrics` or `Meta lists hold at most 6 items` |
| A count on a choice without integration results | `Only integration results carry a count` |
| A destructive action without a confirm | `Destructive actions need a confirm` |
| An icon on a toned callout or badge | `Only neutral callouts take an icon; toned callouts show their tone's glyph` |
| A toned icon without a label | `Toned icons need a label` |
| A reserved icon on a button or menu | `That icon is reserved for Reintersect's own controls` |
| A number format that doesn't fit | `Currency values need a currency code`, `Only currency values take a currency code`, `Only plain numbers take a unit` or `Only number columns take a number format` |
| Progress over its maximum, or a unit without `max` | `Progress value cannot exceed its maximum` or `Progress needs a max to show a unit` |
| A search select's label | `Only search selects take a selectedLabel` or `A search select's value needs its selectedLabel` |
| A donut that adds up to zero | `Donut charts need a positive total` |
| Duplicate names in a table, chart or select | `Column labels must be unique`, `Series names must be unique`, `Point labels must be unique` or `Select option labels must be unique` |

## Block data

| Limit | Value |
| - | - |
| Props, as JSON | 16 KB |
| State, as JSON | 64 KB |
| Form input in one submission, as JSON | 16 KB |
| Images copied into Reintersect | JPEG, PNG, WebP or GIF, 5 MB, 8,192 pixels per side, 4 second download |
| `staleAfter` | 60 seconds to 30 days |

## Actions

| Limit | Value |
| - | - |
| Serialized `args` bound to one button | 2 KB |
| Action name | 1 to 64 characters from `a-z`, `0-9`, `_`, `.`, `-` |
| Actions per block | 64 |
| `notice` | 140 characters |
| Search results returned for a `Select` | 50 |
| Time Reintersect waits for an action, render, insert or reference resolve | 5 seconds |
| Time Reintersect waits for a command or message action answer | 30 seconds |
| Time to send a deferred command or message action answer | 15 minutes |
| How long a private answer stays | 24 hours, unless the member shares or dismisses it |
| Time an action can update its own block with the interaction token | 15 minutes |
| Notifications from `notify` and `POST /v0/notifications` together | 60 a minute per app |

## Manifest

| Limit | Value |
| - | - |
| Blocks per app | 50 |
| Reference kinds per app | 50 |
| Message actions per app | 10 |
| Slash commands per app | 25 |
| Options per command, choices per option | 25 each |
| Sections per block | 32 |
| Environment variables | 128 per environment, values at most 5 KB |
| Outbound hosts (`egress`) | 50 |
| Claimed domains | 20 |
| JSON Schema per props, state, args, input or install config | 5,000 nodes and 256 KB once expanded |
| JSON Schema across the whole manifest | 50,000 nodes and 2 MB, nesting at most 128 levels |
| Hosted bundle | 10 MB |

Recursive schemas, remote `$ref`s, `$dynamicRef` and nested `$id` are rejected at sync with
`schema-too-complex`.

## Identifiers

| Identifier | Format |
| - | - |
| App slug | 3 to 32 characters from `a-z`, `0-9`, `-`; not reserved and not starting with `reintersect` |
| Block type | 1 to 48 characters from `a-z`, `0-9`, `-` |
| Reference kind | 1 to 48 characters from `a-z`, `0-9`, `-` |
| Input names, choice values, pattern ids, message action ids, command option names | 1 to 64 characters from `A-Z`, `a-z`, `0-9`, `_`, `.`, `-` |
| Command names | A lowercase letter, then up to 31 characters from `a-z`, `0-9`, `-` |
| Section names | 1 to 48 characters from `A-Z`, `a-z`, `0-9`, `_`, `-` |
| Environment variable keys | A letter or `_`, then up to 63 letters, digits or `_` |

## References

| Limit | Value |
| - | - |
| URL patterns per reference kind | 50 |
| Path segments per pattern | 16 |
| Named parameters per pattern | 8 |
| URL length | 2,048 characters |
| URLs resolved in one delivery | 20 |
| Search results per query | 50 |

## Events and deliveries

| Limit | Value |
| - | - |
| Lifecycle delivery timeout | 15 seconds |
| Lifecycle retries | Up to 20 attempts with jittered backoff from 1 minute to 6 hours |
| Response body read from your app | 1 MB |
| Signature timestamp tolerance | 5 minutes |

## Hosted apps

| Limit | Value |
| - | - |
| CPU time per delivery or route request | 50 ms |
| CPU time per MCP request | 200 ms |
| Outbound requests per request | 50 |

CPU time counts only time spent computing. Time spent waiting on `fetch` doesn't count toward it,
but it does count toward the delivery deadline.

## Rate limits

| Endpoint | Limit |
| - | - |
| `POST /v0/memories` | 60 a minute per install |
| `POST /v0/notifications` and `notify` results | 60 a minute per app |
| `POST /v0/apps/check/trees` | 60 a minute per caller |

Requests over a limit fail with `ReintersectApiRateLimitExceededError` (HTTP 429).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.