authelia/authelia · error · Error

Failed POST to ${path}. Code: ${res.status}. Message: ${hasS

Error message

Failed POST to ${path}. Code: ${res.status}. Message: ${hasServiceError(res).message}

What it means

Generic failure thrown by PostWithOptionalResponse in Authelia's API client after a POST request. Axios's default validateStatus rejects non-2xx as AxiosError first, so this message fires only for 2xx-but-not-200 responses (e.g. 204) or 200 responses whose body has status 'KO' per hasServiceError. The thrown text embeds path, HTTP code, and the server's message.

Source

Thrown at web/src/services/Client.ts:34

): Promise<T | undefined> {
    const res = await axios.put<ServiceResponse<T>>(path, body, { signal });

    if (res.status !== 200 || hasServiceError(res).errored) {
        throw new Error(`Failed PUT to ${path}. Code: ${res.status}. Message: ${hasServiceError(res).message}`);
    }

    return toData<T>(res);
}

export async function PostWithOptionalResponse<T = undefined>(
    path: string,
    body?: any,
    signal?: AbortSignal,
): Promise<T | undefined> {
    const res = await axios.post<ServiceResponse<T>>(path, body, { signal });

    if (res.status !== 200 || hasServiceError(res).errored) {
        throw new Error(`Failed POST to ${path}. Code: ${res.status}. Message: ${hasServiceError(res).message}`);
    }

    return toData<T>(res);
}

export async function PostWithOptionalResponseRateLimited<T = undefined>(
    path: string,
    body?: any,
    signal?: AbortSignal,
): Promise<RateLimitedData<T> | undefined> {
    const res = await axios.post<ServiceResponse<T>>(path, body, {
        signal,
        validateStatus: validateStatusTooManyRequests,
    });

    if (res.status !== 200 || hasServiceError(res).errored) {
        if (res.status === 429) {
            return toDataRateLimited<T>(res);

View on GitHub (pinned to c883b8d3d8)

Solutions

  1. Read the 'Message:' segment - it is the server's own explanation (e.g. 'invalid credentials', 'user is banned')
  2. Confirm the request payload matches the endpoint's expected schema before retrying
  3. Check backend logs for the matching POST to see the KO reason
  4. Ensure custom endpoints return {status:'OK'} / {status:'KO'} with HTTP 200
  5. Align SPA and backend versions after upgrades

Example fix

// before
await PostWithOptionalResponse('/api/logout', undefined, signal);

// after
try {
    await PostWithOptionalResponse('/api/logout', undefined, signal);
} catch (err) {
    if (err instanceof Error && err.message.startsWith('Failed POST to ')) {
        notify(extractServerMessage(err.message)); // service-level KO
        return;
    }
    throw err; // transport-level failure (non-2xx, network) handled upstream
}
Defensive patterns

Strategy: try-catch

Type guard

function isServiceErrorResponse(body: unknown): body is { status: 'KO'; message: string } {
    return typeof body === 'object' && body !== null && (body as Record<string, unknown>).status === 'KO';
}

Try / catch

try {
    await PostWithOptionalResponse(path, body, signal);
} catch (err) {
    if (err instanceof Error && err.message.startsWith('Failed POST to ')) {
        handleServiceError(err.message);
        return;
    }
    if (axios.isAxiosError(err)) {
        handleTransportError(err);
        return;
    }
    throw err;
}

Prevention

When it happens

Trigger: A POST to endpoints such as /api/firstfactor, /api/logout, or /api/reset-password/identity/start that returns 200 with {status:'KO', message:'...'} (bad credentials shape, banned user, rejected operation) or a non-200 2xx like 204.

Common situations: Submitting an invalid or locked-out first-factor login; backend validation rejecting a password reset start; a proxy or middleware answering 204; custom backend endpoints not following the OK/KO response convention.

Related errors


AI-assisted analysis of authelia/authelia@c883b8d3d8 (2026-08-15). Data as JSON: /api/errors/664255e956179da1. Report an issue: GitHub.