fail
Function, in @jr2/orchestrator/src/fail.ts. It is an export of @jr2/orchestrator, on the Authoring surface page, in Failure.
function fail(): FailSlotFail the run: the Part a Machine invokes to end work that did not succeed. Put it in actors under a name, and invoke it from any state, at any depth: actors: { fail: fail() }, then invoke: { src: "fail", input: { reason } }.
The input is { reason: string; detail?: unknown }. reason is text for a person, and it must not be empty. detail is optional JSON for a machine reader.
The Failure goes up from the state that invokes fail, through each parent Machine, as an error does. An onError on the way catches it; isFailure tells it from a defect. When no state catches it, the run ends failed: its output is { reason, detail }, and jr2 run exits 1. A workspace() that a Failure goes through deletes its Sandbox first.
To fail, invoke fail. Do not throw from a promise to fail: a throw is a defect, and the run ends error. A final state means done: do not use one for work that did not succeed. To keep the work for a person to read, wait at a Gate before the state that fails.
It refuses an input that is not a Failure's, and the run ends error: fail: the input must be { reason: string; detail?: unknown } with a reason that is not empty (got <value>) — invoke: { src: "fail", input: { reason: "the tests failed" } } (ADR-0073).
Returns: The actor logic of the slot.
Example
import { z } from "zod";
import { command, fail, jr2Setup, workspace, type Workspaced } from "@jr2/orchestrator";
const runInput = z.object({ branch: z.string() });
const body = jr2Setup({
types: {} as { input: Workspaced<z.infer<typeof runInput>, "app"> },
actors: {
tests: command(["npm", "test"], { timeout: "15m" }),
fail: fail(),
},
}).createMachine({
id: "check",
on: { "workspace.lost": ".lost" },
initial: "testing",
states: {
testing: {
invoke: {
src: "tests",
onDone: [
{
guard: ({ event }) => event.output.outcome === "exited" && event.output.code === 0,
target: "passed",
},
{ target: "failing" },
],
},
},
// Not a final state: the run ends `failed`, and the Workspace deletes the Sandbox.
failing: { invoke: { src: "fail", input: { reason: "npm test did not pass" } } },
passed: { type: "final" },
lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
},
});
export const machine = workspace(body, {
input: runInput,
repos: { app: "https://github.com/you/app.git" },
spec: ({ input }) => ({ branch: input.branch }),
});See also