Skip to main content
The headline use case: make a specific failure happen on demand, then assert your app handles it. Armed faults are the lever, because they work even when unmodified app code makes the call (see why).

Arm, run, assert

await sandbox.faults.arm("task_runs", "create", {
  status: 402,
  code: "insufficient_funds",
  count: 1,                 // fire once, then auto-clear; omit `count` to leave it armed
});

const deck = sandbox.client();
await expect(
  deck.taskRuns.create({ taskId: "task_rent" }),
).rejects.toMatchObject({ code: "insufficient_funds", status: 402 });
The fault returns Deck’s real error envelope — the pack defines its shape, so your error-handling code sees exactly what production sends.

Narrow which calls it hits

An un-narrowed fault hits every matching resource + operation. Scope it so non-matching calls fall through to normal handling:
await sandbox.faults.arm("task_runs", "create", {
  status: 402,
  code: "insufficient_funds",
  match: { input: { taskId: "task_rent" } },  // only rent runs decline; other tasks succeed
});

Clear it

count auto-clears after N fires. Clear manually when you armed it open-ended:
await sandbox.faults.clear();        // clear all
await sandbox.faults.clear("flt_1"); // clear one by id
Two other ways to force outcomes, for calls your test makes directly: the X-Mock-Scenario header for a one-off named scenario, and pack-defined magic values (Stripe-style test inputs). Both ride inside the request, so they don’t reach an unmodified app’s call path — that’s why armed faults are the default. See Interception.