Error handling
AniLink normalizes every transport failure into an AniLinkError subclass with a stable code. You classify failures by instanceof or by code — never by parsing messages.
Error hierarchy
| Class | Code | When it is thrown |
|---|---|---|
AniLinkError | varies | Base class for all normalized failures |
AniLinkApiError | API_ERROR | Non-success HTTP response. Exposes status, data, rateLimit |
AniLinkGraphQLError | GRAPHQL_ERROR | AniList returned HTTP 200 with GraphQL errors. Exposes graphqlErrors and any partial data |
AniLinkRestError | API_ERROR | REST-specific API failure (MAL surface) |
AniLinkNetworkError | NETWORK_ERROR, TIMEOUT_ERROR, ABORTED_ERROR, CIRCUIT_OPEN_ERROR | Transport failures. Timeout errors carry timeoutMs |
AniLinkAuthError | AUTH_ERROR | Calling an authenticated operation without a token, or the provider rejecting the token |
AniLinkValidationError | VALIDATION_ERROR | Invalid variables or options before a request is sent |
Stable codes
AniLinkErrorCodes maps every code: API_ERROR, GRAPHQL_ERROR, NETWORK_ERROR, TIMEOUT_ERROR, ABORTED_ERROR, CIRCUIT_OPEN_ERROR, AUTH_ERROR, VALIDATION_ERROR, UNKNOWN_ERROR.
Canonical catch-and-classify recipe
import {
AniLinkApiError,
AniLinkAuthError,
AniLinkGraphQLError,
AniLinkNetworkError,
} from "anilink-api-wrapper";
try {
const user = await aniLink.anilist.query.user({ id: 542244 });
} catch (error: unknown) {
if (error instanceof AniLinkGraphQLError) {
console.error(error.graphqlErrors.map((e) => e.message));
console.error(error.data); // partial data, when present
} else if (error instanceof AniLinkApiError) {
console.error(error.code, error.status, error.data);
if (error.status === 429) {
console.error("Quota reset at:", error.rateLimit?.reset);
}
} else if (error instanceof AniLinkAuthError) {
console.error("Token missing or rejected:", error.code);
} else if (error instanceof AniLinkNetworkError) {
console.error(error.code, error.message);
} else {
throw error;
}
}Provider-specific status behavior
Provider scope
- AniList reports rate limits through
x-ratelimit-*headers. EveryAniLinkApiErrorexposes them as a read-onlyrateLimitobject (limit,remaining,reset). - MAL uses the
X-RateLimit-*/Retry-Afterheader family. The samerateLimitobject is populated when those headers are present.
Common AniList statuses: 400 (invalid query/variables), 401 (invalid token), 403 (forbidden), 429 (rate limited), 500/502/503/504 (server-side). Common MAL statuses: 400 (invalid fields), 401 (expired/invalid token), 404 (unknown ID), 429 (rate limited).
Raw error debugging
Pass exposeRawAxiosError: true to attach the original Axios error as rawAxiosError (and cause) on thrown errors.
Caution
Raw Axios errors contain request configuration including bearer-token headers. Enable this only for local debugging. Never log rawAxiosError in production.
Next steps
- Retries & resilience — which failures retry automatically.
- Operation reference — per-operation error lists.