Guides
Error Handling
Handle errors at every level of your application
Spoosh provides multiple layers for handling errors: per-hook, per-trigger, global plugins, and typed errors.
Basic Error Handling
All Spoosh hooks return an error property:
function UserProfile() {
const { data, error, loading } = useRead(
(api) => api("users/:id").GET({ params: { id: "1" } })
);
if (loading) return <div>Loading...</div>;
if (error) {
return <div>Failed to load profile: {error.message}</div>;
}
return <div>{data?.name}</div>;
}Typed Errors
Define a global error type through the second generic parameter on Spoosh. The type flows through to all hooks automatically:
interface ApiError {
message: string;
code: string;
details?: Record<string, string[]>;
}
const spoosh = new Spoosh<ApiSchema, ApiError>("/api").use([...]);Per-Route Error Types
Override the global error type for specific routes by adding an error field to your schema. Routes without error fall back to the global type:
import { SpooshSchema } from "@spoosh/core";
type ApiSchema = SpooshSchema<{
"users/:id": {
GET: {
data: User;
// No error field — uses global ApiError
};
};
"auth/login": {
POST: {
body: { email: string; password: string };
data: { token: string };
error: LoginError; // Overrides global ApiError
};
};
}>;
interface LoginError {
message: string;
code: "INVALID_CREDENTIALS" | "ACCOUNT_LOCKED" | "EMAIL_NOT_VERIFIED";
remainingAttempts?: number;
}Per-Request Error Handling
The trigger function returns a promise with both data and error, letting you handle errors inline with full type inference:
function LoginForm() {
const { trigger } = useWrite((api) => api("auth/login").POST());
const handleSubmit = async () => {
const { data, error } = await trigger({ body: credentials });
if (error) {
// error is typed as LoginError (from schema)
if (error.code === "ACCOUNT_LOCKED") {
showLockedMessage();
return;
}
showToast(error.message);
return;
}
saveToken(data.token);
navigate("/dashboard");
};
}Global Error Handling
Show a toast for all errors globally using a custom plugin:
import { SpooshPlugin } from "@spoosh/core";
function globalErrorPlugin(): SpooshPlugin {
return {
name: "global-error",
operations: ["read", "write", "pages"],
afterResponse: (context, response) => {
const error = response.error as ApiError | undefined;
if (error) {
showToast(`Request failed: ${error.message}`);
}
},
};
}const spoosh = new Spoosh<ApiSchema, Error>("/api").use([
globalErrorPlugin(),
cachePlugin({ staleTime: 5000 }),
invalidationPlugin(),
]);