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

# Errors & replanning

> Why your plans never replan, and what plan_and_execute does differently

The core policy: **who authored the plan determines what failure means.**

## Human-authored plans never replan

When you run a plan — via `plan run` or as a `plan__*` tool — you asked for *that* plan. If a step fails, rewriting your workflow behind your back would be worse than failing, so graph doesn't. You get a structured, attributable error:

```
Error: plan failed at step E2 (linear__list_issues): 'linear' exited with …
```

* `plan run`: non-zero exit, message on stderr.
* As a plan tool: an `is_error` tool result — the agent explains it or works around it *visibly* (you'll see any fallback tool calls in the trace).

## `plan_and_execute` replans

Plans authored by the LLM planner are drafts. Defects trigger a **replan**: the error — including, for bad data references, a digest of the keys that actually exist — feeds back to the planner, which revises the plan. Executed steps are preserved and never re-run; only the broken tail is replaced. After the configured attempts (`planning_attempts`, default 2), it degrades to an honest error summary instead of raw failure.

One idempotency caveat: "executed steps are preserved" is keyed on *top-level* step results. Steps inside a [`decide` branch](/plans/branching) or a [`map`/`reduce` body](/plans/iteration) are scoped to that step, so a control step that fails partway through counts as not executed — a replan that re-authors it re-runs the branch from its first step (or the map from its first item), duplicating any side effects the successful prefix already had. Keep bodies idempotent, or move side-effecting sequences into a `plan__*` call the body invokes. The same applies to an [`agent` step](/plans/agent-step), and more sharply: its rounds are not top-level results either, so a replan re-runs the whole loop — and because the calls were chosen by the model rather than written in the plan, you cannot tell from the YAML what will be repeated. Give agents read-only tool sets unless you have a reason not to.

```
→ plan_and_execute {"query":"…"}
  ✎ planning…
  → linear__list_teams …
  ✗ step E1 failed: bad path 'E0.teams.0.idd' (available: id, name, …)
  ↻ replanning (attempt 2)
  → linear__list_issues …          ← fixed reference, E0 not re-executed
```

## The three failure classes

Template resolution errors are typed ([details](/plans/template-language#error-taxonomy)), and each class routes differently:

| Class                     | Meaning                      | Your plans                                                                                          | `plan_and_execute`                                 |
| ------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| `BadPath` / `MissingStep` | the plan is wrong            | hard failure                                                                                        | replan with key digest                             |
| Tool error                | a step's tool failed         | hard failure — *except* inside an [`agent` step](/plans/agent-step), where it returns into the loop | replan                                             |
| `EmptyData`               | plan fine, **nothing found** | solver explains it (solver mode); typed hard failure (output/silent)                                | straight to solver — replanning can't conjure data |

The `EmptyData` distinction is the one that matters day-to-day: a search returning zero results is an *answer* ("no active cycle"), not a defect. Solver-mode plans report it gracefully; automation-mode plans surface it as `empty_data: true` so pipelines can branch on it.

## Where validation happens

1. **Load time** (automatically on every load, everywhere): YAML shape, template syntax, forward references (`E0` referencing `E2`), id format, control-step inputs (a `decide` gate's arity, a `map`'s body, an [`agent`](/plans/agent-step)'s `output_schema` and budget — inside bodies too), malformed tool names — including `workbench__*`, which is rejected outright: those tools exist only inside the workbench TUI's chat agent, never in the plan runtime, so a step naming one is always a defect. This layer is static and context-free.
2. **Catalog resolution** (`plan validate`, `plan run`, and workbench validation and runs — anywhere the full config context exists): every step tool name, control-step bodies included, is resolved against what is actually loadable — `builtin__*` against the enabled packs, `user__*` against `[tools].paths`, `plan__*` against the plan catalog (followed transitively through composed plans). An [`agent` step](/plans/agent-step)'s `tools:` patterns are resolved the same way, wildcards included — `linear__*` requires `[mcp.linear]`, `user__*` must match at least one loadable user tool — so a plan that names tools which cannot load fails here rather than mid-agent. MCP `server__tool` names are verified at the *server* level — the server must be configured under `[mcp.*]` — because listing a server's real tools would mean connecting, which validation never does; the individual tool name is still checked at dispatch. An unresolvable tool fails the run **before any step executes**, so no tool calls or LLM money are spent on a plan that cannot finish. The one soft case: a server that is unconfigured but declared in `requires_servers` is a *note*, not an error, when validating a plan **file** — the file is portable and its dependency is declared — but the plan is [hidden from the catalog](/plans/overview#plan-discovery) and running it by name reports the missing servers.
3. **Input time**: JSON Schema validation of inputs, before any step runs.
4. **Run time**: everything that depends on real data — path existence against actual results, tool errors, emptiness, and MCP tool existence within a verified server.

The design accepts that run-time is where data-shaped errors belong: with MCP tools that don't declare output schemas, pretending to verify paths statically would be false confidence. Instead, run-time errors are made maximally actionable (key digests) and the [shape cache](/tools/shape-cache) shrinks the unknown over time. Planner-authored plans (`plan_and_execute`) skip catalog resolution: the planner draws from the live registry, and execution plus replanning already handle its misfires.


## Related topics

- [The planner](/plans/the-planner.md)
- [Finish modes](/plans/finish-modes.md)
- [Template language](/plans/template-language.md)
- [Agent steps](/plans/agent-step.md)
- [Scripting contract](/reference/scripting-contract.md)
