---
title: isFailure
description: Is this error a Failure, which a state invoked `fail` to make?
---

# `isFailure`

Function, in `@jr2/orchestrator/src/fail.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Failure.

```ts
function isFailure(error: unknown): error is Failure
```

Is this error a Failure, which a state invoked `fail` to make? A defect — any other error — is
not. Use it in the guard of an `onError` to catch a Failure and let a defect go up, and read the
Failure's `reason` and `detail` from the error it narrows.

**Parameters**

- `error`: The error of an error event: `event.error` in an `onError`.

**Returns**: True for a Failure, with `error` narrowed to `{ reason, detail? }`.

**Example**

```ts
import { z } from "zod";
import { defineEvent, fail, isFailure, jr2Setup } from "@jr2/orchestrator";

const retry = defineEvent({ name: "retry", description: "Try the plan again.", input: z.object({}) });

const attempt = jr2Setup({ actors: { fail: fail() } }).createMachine({
  id: "attempt",
  initial: "stuck",
  states: { stuck: { invoke: { src: "fail", input: { reason: "no plan fits the ticket" } } } },
});

export const machine = jr2Setup({ events: [retry], actors: { attempt } }).createMachine({
  id: "planner",
  initial: "planning",
  states: {
    planning: {
      invoke: {
        src: "attempt",
        onDone: "planned",
        // A Failure waits for a person; a defect has no route, so it goes up and the run ends `error`.
        onError: { guard: ({ event }) => isFailure(event.error), target: "asking" },
      },
    },
    asking: { invoke: { src: "gate" }, on: { retry: "planning" } },
    planned: { type: "final" },
  },
});
```

**See also**

- [ADR-0073: A Machine fails a run with `fail()`, and an uncaught Failure ends it `failed`](../decisions/0073-a-machine-fails-a-run-with-fail-and-an-uncaught-failure-ends-it-failed.md)
