Skip to content

Errors and boundaries

SAPA distinguishes malformed boundary input, expected business outcomes, and unexpected defects.

Public Schemas parse raw input into constrained values. Workflow functions that accept unknown, such as createCheckout and registerOffers, perform strict decoding before invoking application capabilities.

import { Offer } from "@byfungsi/sapa";
import { Effect } from "effect";
const checked = Offer.parse(rawOffer).pipe(
Effect.catchTag("SchemaError", () =>
Effect.fail({ code: "invalid_merchant_offer" as const }),
),
);

Prefer the operation’s documented public error union when it already normalizes schema failures. Do not expose raw parse issue trees, provider responses, storage errors, secrets, or license keys to untrusted callers.

Checkout rejection, stale state, missing definitions, insufficient credits, and invalid commands belong in Effect’s typed error channel. Handle them with Effect.catchTag, Effect.catchTags, or exhaustive matching appropriate to the published union.

Reserve thrown exceptions and Effect defects for violated programmer assumptions or framework failures that cannot be represented as an expected operation outcome. Do not convert ordinary domain rejection into a defect just to simplify a return type.

Log stable operation names, safe identifiers, and public error codes. Redact credentials and avoid including raw customer or provider payloads. Public SAPA errors are intentionally normalized at the facade boundary.