# Error Handling (/docs/products/ussd-flows/developers/error-handling)

There are two kinds of errors in a flow:

- **Input errors.** The subscriber typed something a prompt or menu doesn't accept. They see a message and can try again.
- **Flow errors.** Something in the flow or your server is wrong. The subscriber sees "Flow error:" followed by the reason, and the session ends.

Some mistakes are caught earlier, when you save the flow: bad JSON, fields a page type doesn't accept, and a literal `next_page` that names a page that doesn't exist.

## Input Errors

| The subscriber sees                                        | Cause                                           |
| ---------------------------------------------------------- | ----------------------------------------------- |
| Your `pattern_mismatch_message`, or "Invalid input."       | The answer doesn't match `pattern`              |
| "Invalid input. Expecting at least 8 characters"           | Shorter than `min_length`                       |
| "Invalid input. Expecting at most 16 characters"           | Longer than `max_length`                        |
| "Invalid input. Expecting a number"                        | Not a number on an `integer` or `double` prompt |
| "Invalid input; value must not be less than …"             | Below `min_value`                               |
| "Invalid input; value must not be greater than …"          | Above `max_value`                               |
| "Invalid input; expecting '1' for 'Yes' or '2' for 'No'"   | Not a yes or no on a `boolean` prompt           |
| "Invalid selection. Input must be a number between 1 to …" | Not a listed number on a menu                   |

A prompt allows `max_invalid_input_attempts` tries (default 3, up to 5). A menu allows 3. After that, the session ends. See [Prompt](/docs/products/ussd-flows/developers/page-types/prompt).

## Variable Errors

Unset `rc.*` and `sc.*` values show as empty. Other missing values stop the flow. [Variables](/docs/products/ussd-flows/developers/variables) explains which references can be empty.

| Flow error                                          | Cause                                                                          | Fix                                                                                                             |
| --------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| "No page data found for key: 'balance' in page '…'" | `$(data.balance)` on a page your server sent no `balance` for                  | Send the key in `pageData` of the response that opens this page                                                 |
| "No page value for page '…'"                        | `$(page.ID.value)` for a page that was skipped or not reached yet              | Make sure the page always runs first, or read it inside an expression with a fallback: `$(page.ID.value ?? '')` |
| "Invalid page value reference: …"                   | The page ID doesn't exist                                                      | Fix the spelling. IDs are case-sensitive                                                                        |
| "Invalid session property reference: …"             | Unknown `session.*` name                                                       | Use one of the names in [Variables](/docs/products/ussd-flows/developers/variables)                             |
| "Bad variable declaration …"                        | A page reference other than `.value` or `.label`, such as `$(page.pay.status)` | Use `$(page.ID.value)` or `$(page.ID.label)`                                                                    |

## Expression Errors

| Flow error                             | Cause                                                            | Fix                                                                                 |
| -------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| "Undefined variable '…' in expression" | A name that isn't a variable, often a typo such as `rcc.balance` | Fix the name. Variables start with `page.`, `data.`, `session.`, `rc.` or `sc.`     |
| "Unable to parse expression"           | Unbalanced brackets, a stray operator, or bad quotes             | Simplify the expression and add parts back one at a time                            |
| "Bad function '…'"                     | A function that doesn't exist, such as `strings.reverse`         | Use a function from [Expressions](/docs/products/ussd-flows/developers/expressions) |
| "Unknown function namespace '…'"       | A namespace other than `strings`, `datetime` or `subscriber`     | Use one of those, or a global function                                              |

## Context Store Errors

| Flow error                                                | Cause                                                                          | Fix                                                                                              |
| --------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| "Invalid key '…'"                                         | The key doesn't match `^[a-zA-Z_][a-zA-Z0-9_]{0,32}$`                          | Start with a letter or underscore. Use only letters, digits and underscores, up to 33 characters |
| "Recurring context size exceeds maximum '16'"             | A 17th `rc.*` key for this subscriber and flow                                 | Clear unused keys with `null`, or combine related keys                                           |
| "Unexpected value type for key '…'"                       | The key already holds a different type, for example a boolean and now a string | Keep one type per key, or clear it with `null` first                                             |
| "String value for key '…' is greater maximum value '100'" | A string longer than 100 characters                                            | Shorten it with `strings.truncate(s, 97)` (it adds "..."), or keep it on your server             |

See [Context Stores](/docs/products/ussd-flows/developers/context-stores).

## Exchange Errors

Monime waits 10 seconds for your endpoint. Any of these ends the session:

| Flow error                                                                 | Cause                                        | Fix                                                                                          |
| -------------------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- |
| "Flow exchange failed for page '…'"                                        | Timeout, DNS failure, or no connection       | Check the URL and that your server can be reached from the internet. Reply within 10 seconds |
| "Flow exchange response error for page …"                                  | Your server returned a status other than 200 | Return 200, and use `stop` for your own errors                                               |
| "Flow exchange response returns null 'action'"                             | The response has no `action`                 | Return `"navigate"` or `"stop"`                                                              |
| "Flow exchange response 'message' must not be null when action is 'stop'." | A `stop` without `message`                   | Add a `message`                                                                              |
| "No next page found for next page id: …"                                   | `pageId` names a page that doesn't exist     | Match a page `id` exactly, including case                                                    |

When your server can't complete a request, return `stop` with a message rather than an error status:

```json
{
  "action": "stop",
  "message": "We can't check your account right now. Please try again in a few minutes."
}
```

See [Exchange & Dynamic API](/docs/products/ussd-flows/developers/exchange-api/overview).

## Navigation Errors

| Flow error                                            | Cause                                                      | Fix                                                           |
| ----------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------- |
| "No page found with id: '…'"                          | A `next_page` expression gave a page ID that doesn't exist | Check every value the expression can return                   |
| "Flow terminated unexpectedly: no next page defined." | The last page in the flow isn't a display page             | End every path with a display page, or use `options.terminal` |
| "Flow reaches end; too many page skips."              | Every page after this point was skipped                    | Make sure at least one later page always runs                 |

## Payment Errors

See [collect\_payment](/docs/products/ussd-flows/developers/templates/collect-payment#errors).

## Side-Effect Page Errors

See [Side Effect](/docs/products/ussd-flows/developers/page-types/side-effect#common-mistakes).

## Writing Messages for Subscribers

These rules apply to your `pattern_mismatch_message`, `exit_message`, `stop` messages and error pages:

- Say what's wrong, then what to do: "Account numbers have 8 to 16 characters. Try again."
- Keep it short. The screen is small.
- Don't show internal details: "We can't check your account right now", not "Database connection timeout".
- Log the details on your server instead.
