# Test Error States

Force the states a happy-path run never reaches (a failing API, an empty list, a slow...

- Repository: https://github.com/reticlehq/reticle (1299 stars)
- Category: Design
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add reticlehq/reticle --skill test-error-states -g -a claude-code -y`
Codex: `npx skills add reticlehq/reticle --skill test-error-states -g -a codex -y`
Cursor: `npx skills add reticlehq/reticle --skill test-error-states -g -a cursor -y`
Gemini CLI: `npx skills add reticlehq/reticle --skill test-error-states -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add reticlehq/reticle`

## Description

Force the states a happy-path run never reaches (a failing API, an empty list, a slow request, a timeout, an expired session, a toast that auto-dismisses) and check the UI actually handles them. Use when error handling was written but never run, when a loading or empty state needs verifying, when a bug only happens on a slow connection, or when a timer, poll, debounce or retry needs testing without sleeping.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# The error state has never run

Every app has a `catch` block nobody has executed and an empty state nobody has seen. They are written from imagination, shipped untested, and discovered by a user on a bad day.

**Reticle** can force those conditions in the running app. Not set up? Follow the [`reticle`](https://github.com/reticlehq/reticle/blob/main/skills/reticle/SKILL.md) skill: it installs Reticle, asks the user before `init` changes the app's files, and proves one flow.

## Read this before you start: network mocking needs a driven or leased browser

`reticle_network_mock` intercepts requests in a browser Reticle owns, and **the always-on SDK cannot do it.** A connected tab with neither `reticle drive` nor a lease still returns `{ ok: false, reason: "no-cdp-provider" }`.

Your route is a leased Playwright tab (`reticle_run { tool: "reticle_lease", args: { action: "acquire", url } }`) or `RETICLE_CDP_URL` pointed at a Chrome started with remote debugging:

```bash
# macOS, the user runs this once, in their own Chrome
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

RETICLE_CDP_URL=http://localhost:9222 npx @reticlehq/server@latest mcp
```

If you have neither a lease nor a driven browser, **say so in one line and offer the clock half of this skill anyway**: `reticle_clock` needs none of it. What you may not do is drive the happy path, watch it pass, and report that error handling works.

## Force a failure

```
reticle_run({ tool: "reticle_network_mock", sessionId, args: {
  mocks: [{ urlContains: "/api/deploys", status: 500 }],
}})
```

Then drive the flow and **name the recovery you expect before you act**:

```
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
  { kind: "element", query: { testid: "error-banner" } },
  { kind: "console", level: "error", absent: true },
]}})
```

The rest: https://github.com/reticlehq/reticle/blob/HEAD/skills/test-error-states/SKILL.md
