Error normalization
Every hook wraps its underlying core action and pipes failures through normalizeSymmError — a classifier that turns any thrown exception (viem, axios, SDK, user rejection) into a single discriminated type: SymmioRequestError. Consumers handle errors by switching on .kind instead of learning multiple error hierarchies.
SymmioRequestError
export type SymmioRequestError =
| { kind: "user-rejected"; message: string; cause?: unknown }
| { kind: "config"; code: string; message: string; cause?: unknown }
| { kind: "validation"; code: string; message: string; cause?: unknown }
| { kind: "api"; code: string; message: string; status?: number; responseData?: unknown; cause?: unknown }
| { kind: "revert"; reason?: string; message: string; cause?: unknown }
| { kind: "unknown"; message: string; cause?: unknown };Every hook’s error typed as SymmioRequestError | null. Discriminate on .kind:
const mutation = useAllocate();
if (mutation.error) {
switch (mutation.error.kind) {
case "user-rejected":
return null; // silent — user dismissed
case "revert":
return <Toast type="error">Revert: {mutation.error.reason ?? mutation.error.message}</Toast>;
case "api":
return (
<Toast type="error">
API {mutation.error.status}: {mutation.error.message}
</Toast>
);
default:
return <Toast type="error">{mutation.error.message}</Toast>;
}
}normalizeSymmError
import { normalizeSymmError } from "@symmio/trading-react";
const normalized = normalizeSymmError(someUnknownError);Classification order (first match wins):
- Already a
SymmioRequestError— passthrough. - viem
UserRejectedRequestError(walked viaBaseError.walk) →kind: "user-rejected". - viem
ContractFunctionRevertedError→kind: "revert"withreasonextracted. - Other viem
BaseError(call execution failure, gas estimation, RPC) →kind: "revert"with the walked short message. SymmApiError(HTTP failure) →kind: "api"withstatus,code,responseData.SymmErrorwithkind: "config"→kind: "config"with the SDK code.SymmErrorwithkind: "validation"→kind: "validation"with the SDK code.- Anything else →
kind: "unknown"with the rawmessage.
The original error is preserved on cause — logging or DevTools panels still get the full viem / axios / whatever stack.
Why not instanceof?
- Works across realms (SSR, iframes, package duplication).
- Works with any user-space custom error (e.g. wallet connectors that throw their own types).
- Compact — one type, one switch.
instanceof SymmError still works if you prefer it inside a manual try/catch around a core action; the React layer just makes the discriminated form the default so switch on .kind is always safe.
Related
- Core errors — full
SymmError/SymmApiErrorcatalogue. - Hook pattern — where the normalization runs.
Last updated on