ClientError
The error API, RPC and Socket clients use to reject an error response from the server, with its code, status, requestId and per-field issues.
Se autoimporta en los componentes y en app/.
import { ClientError } from "@meekojs/meeko/framework";ClientError is what the browser and server code receive when an api.*, rpc.*, useApi, useRpcQuery, useApiMutation or useRpcMutation call ends in an error response. It is the other side of ApiError: it carries the public code and status, the request's requestId and, if present, per-field issues. A Socket channel rejected due to session or authorization also delivers a ClientError (401 UNAUTHENTICATED or 403 FORBIDDEN).
Its message is the code. An error response without a code uses HTTP_ERROR, and a successful response that is not JSON uses INVALID_RESPONSE.
Usage#
import { ClientError } from "@meekojs/meeko/framework";
export async function rename(call: () => Promise<unknown>): Promise<string | null> {
try {
await call();
return null;
} catch (error) {
if (error instanceof ClientError && error.status === 409) return "That name already exists.";
if (error instanceof ClientError) console.warn(error.code, error.requestId);
throw error;
}
}Type#
class ClientError extends Error {
constructor(
code: string,
status: number,
requestId?: string,
issues?: readonly ValidationIssue[],
);
}interface ValidationIssue {
readonly path: string
readonly message: string
}Parameters#
new ClientError(code, status, requestId?, issues?). You do not normally create it manually: Meeko clients create it.
| Parameter | Type | Default | Description |
|---|---|---|---|
code |
string |
required | The public code, which is also the message. |
status |
number |
required | The HTTP status. |
requestId |
string |
none | The request ID, the same as the x-request-id header and server logs. |
issues |
readonly { path, message }[] |
none | Per-field messages from a validation 400 or an ApiError with issues. |
Return value#
An Error instance with name: "ClientError", code, status, requestId and issues, all read-only. issues is undefined if the response does not include them.
Examples#
Per-field messages without useForm#
import { ClientError } from "@meekojs/meeko/framework";
export function fieldMessage(error: unknown, path: string): string | undefined {
return error instanceof ClientError ? error.issues?.find((issue) => issue.path === path)?.message : undefined;
}With useRpcMutation, fieldMessage(login.error.value, "password") returns the schema's message for that field. useForm handles this distribution for you.
Distinguish an expected error from a network failure#
fetch rejects with a TypeError when there is no network; the server error is a ClientError:
import { isClientError } from "@meekojs/meeko/framework";
export function errorText(failure: unknown): string {
if (isClientError(failure, "RATE_LIMITED")) return "Too many attempts. Wait a moment.";
if (isClientError(failure)) return `Could not save (${failure.code}).`;
return "Could not connect. Try again.";
}This is the typical form of useForm's errorMessage.
Common mistakes#
Read message expecting the server's text#
message is the code, not the internal ApiError message, which never leaves the server.
alert(error.message); // "EMAIL_TAKEN"alert(error.issues?.[0]?.message ?? "Could not create the account.");Read properties of an unknown without checking#
In a catch or error observer, the error is unknown.
try { await save(); } catch (error) { console.log(error.code); }TS18046: 'error' is of type 'unknown'.
try { await save(); } catch (error) { if (isClientError(error)) console.log(error.code); else throw error; }instanceof with two copies of Meeko#
With two copies of the package on the same page (a linked package, a duplicated dependency), instanceof ClientError fails for an error from the other copy, without any warning.
if (error instanceof ClientError && error.code === "UNAUTHENTICATED") location.assign("/login");if (isClientError(error, "UNAUTHENTICATED")) location.assign("/login");Notes#
- Origin. Generated clients create it from the error JSON
{ code, status, requestId, issues? }. An unknown500arrives asINTERNAL_ERROR, without details. - Observers. A
ClientErroris an expected response:useFormdoes not send it to the component's error observer, but does send any other failure. - Support. Display or log
requestId: it is the same ID the server writes in its logs, so you can find the failure.