Errors, Refusals and Empty States

By the Syncfusion DevTutorials team · Last updated

Timeouts, tool failures, refusals, rate limits and "I don't know" are screens you design. Give each one plain words and a next step, then export your v1 AI UX kit.

When the AI Fails

Designed state = a screen you planned for a failure: what happened, what is safe, and what to do next.

In this lesson, you will design a screen for each of the five ways an AI feature fails. Then you will export your v1 AI UX kit.

AI features fail more often than normal buttons. Tools time out. Services break. The model refuses. The provider says "too many requests". Sometimes there is simply no answer.

Most apps show the raw error, or nothing at all.

Press Play, or use Next to go one step at a time.

  • Frames 1 to 5: one failure each. The left side shows the raw error. The right side shows a designed state.
  • The "What this shows" panel: what happened, and the next step.
  • Frame 6: five failures, five different screens.

Simple lesson: a failure is a screen you design, not an accident you show.

A Real-World Example

Think about a cash machine.

  • When it runs out of notes, it does not show "ERR_CASSETTE_EMPTY". It says "Unable to dispense cash. Your account has not been charged."
  • When the network is down, it says "Service unavailable. Please use another machine."
  • When you enter the wrong PIN, it says how many tries are left.

Each message says what happened, what is safe, and what to do.

AI failures need the same care:

  • "Your account has not been charged" = what is safe.
  • "Please use another machine" = the next step.
  • A different message for each problem = a designed state per failure.

Click the button. The Build tab plays a tool failure through the naive interface.

  • The screen: "TypeError: Cannot read properties of undefined".
  • The Scenario list: five failures to try, one by one.
  • The checks: each raw error fails.

Simple lesson: a support agent cannot act on a stack trace.

What You Will Learn

In this lesson, you will learn:

  1. The five ways an AI feature fails.
  2. The three parts of a designed state.
  3. Why one generic message is not enough.
  4. Why a blank screen is the worst answer.
  5. How to export your v1 AI UX kit.

About failures in this lab

  • Each failure scenario in the Build tab sends one error event with a raw message, like a real service would.
  • Your interface decides what the user sees: the raw message, nothing, or a designed state.
  • The raw messages are real-looking on purpose. Real services send text like this every day.

Five Ways AI Fails

FailureWhat happenedA good next step
TimeoutA tool or the model took too longTry again; the question is saved
Tool failureA service the agent uses brokeTry again; nothing was changed
RefusalThe model said no on purposeAsk about something it can help with
Rate limitToo many requests right nowRetry after the wait, and say how long
"I don't know"There is no answer in the dataCheck the input, or search another way

Refusal = the model declines a request on purpose, for example to protect private data.

Rate limit = a provider's cap on how many requests you can send in a time window.

Simple lesson: five failures, five different causes, five different next steps.

The Three Parts of a Designed State

Every designed state has three parts:

  1. What happened, in plain words. "We could not open the order."
  2. What is safe. "Nothing was changed." "Your question is saved."
  3. What to do next, as one button that starts with a verb. "Try again." "Search orders."
const AI_STATES = {
  tool: { title: "We could not open the order", body: "The order system had a problem. Nothing was changed.", action: "Try again" },
  rate: { title: "The assistant is busy", body: "Your question is saved and will be ready to send in 20 seconds.", action: "Retry in 20 s" },
};

function AiState({ code, onAction }: { code: keyof typeof AI_STATES; onAction: () => void }) {
  const s = AI_STATES[code];
  return (
    <div role="status">
      <strong>{s.title}</strong>
      <p>{s.body}</p>
      <button onClick={onAction}>{s.action}</button>
    </div>
  );
}

Log the raw error for your team. Show the designed state to the user.

Easy way to remember: What happened? What is safe? What now? Every failure screen answers all three.

Simple lesson: plain words, what is safe, one helpful button.

One Message Is Not Enough

Many apps use one message for everything: "Something went wrong. Please try again."

But "try again" does not fix every failure.

Step through both frames.

  • Frame 1: a rate limit. Trying again at once fails again, because the limit has not reset.
  • Frame 2: a refusal. Trying again is refused again, because the request itself is the problem.

Simple lesson: each failure needs its own next step.

The Blank Screen

The worst failure screen is no screen at all. The spinner disappears and nothing replaces it. The user does not know if it worked, failed or is still running.

Step through all three frames.

  • Frames 1 and 2: on the left, a spinner. On the right, the slow step is named.
  • Frame 3: the request times out. The left side goes blank. The right side says the question is saved, with Try again.

"I don't know" is a good answer, if you design it.

  • An agent that makes something up is worse than one that says it found nothing.
  • Give "I don't know" its own screen with a next step, so it does not feel like a failure.
  • Lesson 3's "not sure" state is the gentle version of this.

Simple lesson: never leave the user with nothing.

Lab Exercise: Design Every Failure

Your task: change the Lesson 6 choices in the Build tab so all five failure scenarios pass. Then press Check all scenarios.

Click the button and open the Build tab.

  • Each failure: choose "Designed state with a next step".
  • Play each scenario: compare the designed state with the raw one.
  • A failing check: quotes what the user would see instead.

Simple lesson: five designed states, one per failure.

Export Your v1 AI UX Kit

You have now built the whole first half of the course:

LessonWhat you built
2Streaming, tool steps, a skeleton and a real Stop
3Citation chips, a "not sure" banner and a scope note
4Stop, Edit, Retry with versions, and snapshot Undo
5A preview card, confirm by risk and an undo window
6A designed state for every failure

v1 kit = a zip with React components for each pattern, a config file with your choices, and the lab's checks as Playwright tests.

Click the button and open the Export tab.

  • The table: which lessons pass every check with your interface.
  • The file list: read each file before you download.
  • Download: saves ai-ux-kit-v1.zip. The components need no library.

The Playwright tests start as "fixme". Point each one at your own app, then remove "fixme". Test them against your stack: the lab's rules are the same, but your app's details are not.

Simple lesson: your kit is the five lessons as code you can use.

What Changes per Framework

OptionError and empty states
Hand-built ReactA state per error code, as above
CopilotKitCatch errors from the agent run and render your own state
Vercel AI SDK UIuseChat exposes an error; map it to your states
Syncfusion AI componentsTemplates for the reply area (optional, not graded)

Build It in React

In the Code tab, failures arrive as an error event with a code and a raw message. The starter prints raw on the screen. Your version logs raw for the team and shows a designed state for the user.

if (e.type === "error") { console.error(e.raw); setCode(e.code); }

Write one state per code: a title, what is safe, and a button for the next step.

TL;DR

  1. Designed state = a planned screen for a failure.
  2. Five failures = timeout, tool failure, refusal, rate limit, "I don't know".
  3. Three parts = what happened, what is safe, what to do next.
  4. One message is not enough = each failure needs its own next step.
  5. Never blank = the user must always see something.
  6. v1 kit = your Lesson 2 to 6 interface as React components and tests.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Showing the raw error"It's honest."Log it; show plain words.Users see "TypeError" and lose trust.
One message for everything"Something went wrong" covers it.One state per failure."Try again" fails again on a rate limit.
A blank panel"The spinner stopped, so it's done."Always show a state.Users wait, then give up.
Not saying what is safe"They know nothing happened."Say "Nothing was charged" or "Your question is saved".Users worry, and retry a payment twice.
Hiding "I don't know""Always give an answer."Design the no-answer state.The agent makes something up.

Check Your Understanding

Exercises

What to Remember

  • AI fails more often than normal buttons. Plan for it.
  • Five failures: timeout, tool failure, refusal, rate limit, "I don't know".
  • Each designed state says what happened, what is safe and what to do next.
  • One generic message sends people in circles.
  • Never leave the screen blank.
  • Export your v1 kit and wire its tests to your own app.

Further Reading

Next: Controlled Generative UI, where the agent stops writing walls of text and picks from your own components: an order card, a refund form and a tracking timeline.