Release candidate — 1.0.0-rc.6
StitchAPI

Errors & pitfalls

How StitchAPI errors work, the code-to-docs contract, and an index of every coded failure.

When a stitch can't produce a result, it fails with a StitchError — an Error subclass exported from stitchapi, carrying a human-readable message, an optional .status (the upstream HTTP status), and .attempts (how many tries the runtime made before giving up). When the failure came from an HTTP response it also carries .body (the parsed error payload — an API's { error: "…" }) and .url (the final request URL, after redirects); both are undefined for transport/internal errors. Await a stitch and that error is what catch receives — narrow it with instanceof:

import { ,  } from 'stitchapi';

const  = ({
    : 'https://api.example.com',
    : '/me',
});

try {
    await ();
} catch () {
    if ( instanceof ) {
        // .body is the parsed error payload; .url is the final request URL.
        .(., ., ., ., .);
    }
}

.body carries the upstream error payload only to the awaited / .safe() caller — it rides a non-enumerable channel and is never written to a trace sink, so an { error: "…" } payload can't leak into a JSONL/console log. If a non-2xx is actually expected control flow (a 404 you fall back from), see acceptStatus — it returns the body as a normal result instead of throwing.

If you read the event stream instead of awaiting, the same failure arrives as an error event carrying { name, message, status?, attempts, at }attempts is how many tries the runtime made before giving up, at is when it gave up.

Handle failure without throwing

await and .unwrap() throw on failure. When you'd rather branch than wrap the call in try/catch, .safe() consumes the call and never throws — it resolves to a discriminated { ok, data, error }, where error is the same StitchError, or null on success:

import {  } from 'stitchapi';

const  = ({ : 'https://api.example.com', : '/me' });

const { ,  } = await .();
if () .(., .);
else .(); // the validated result; error is null here

.unwrap() is the explicit throwing twin of .safe() — the value, or a thrown StitchError, exactly like awaiting the bare call. See the event stream for the iterate-instead-of-await view of the same outcomes.

The code-to-docs contract

Each catalog page below owns a stable code (STITCH_VALIDATION, STITCH_DRIFT, and so on). The code's page slug is its URL — the failure documented at /errors/<slug> is the page the runtime will deep-link to from a thrown error. Slugs are an API: once a page is published its slug is never renamed, only added-and-redirected, so a link a runtime emitted a year ago still resolves.

These codes are provisional. Today the runtime throws a StitchError with a message and optional .status — the stable code and url fields land with the error-taxonomy refactor. The slugs below are already fixed, so you can rely on the URLs even while the in-runtime codes are still on the way.

Every coded failure

Debugging one of these with an agent? Connect the docs MCP and it can pull any error page on demand — search_docs('STITCH_DRIFT'), search_docs('rate limit') — instead of guessing from stale training data.

See also

On this page