Skip to content
AniLink

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

ClassCodeWhen it is thrown
AniLinkErrorvariesBase class for all normalized failures
AniLinkApiErrorAPI_ERRORNon-success HTTP response. Exposes status, data, rateLimit
AniLinkGraphQLErrorGRAPHQL_ERRORAniList returned HTTP 200 with GraphQL errors. Exposes graphqlErrors and any partial data
AniLinkRestErrorAPI_ERRORREST-specific API failure (MAL surface)
AniLinkNetworkErrorNETWORK_ERROR, TIMEOUT_ERROR, ABORTED_ERROR, CIRCUIT_OPEN_ERRORTransport failures. Timeout errors carry timeoutMs
AniLinkAuthErrorAUTH_ERRORCalling an authenticated operation without a token, or the provider rejecting the token
AniLinkValidationErrorVALIDATION_ERRORInvalid 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

typescript
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. Every AniLinkApiError exposes them as a read-only rateLimit object (limit, remaining, reset).
  • MAL uses the X-RateLimit-* / Retry-After header family. The same rateLimit object 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

AniLink — typed AniList & MyAnimeList client for TypeScript.