handle backend errors
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 10s

This commit is contained in:
2026-08-03 18:30:52 +05:00
parent c6015e27a6
commit 7d94a15ca3
3 changed files with 26 additions and 2 deletions
+1 -1
View File
@@ -188,7 +188,7 @@ export default function SignUpForm() {
<SelectContent>
<SelectGroup>
<SelectLabel>Atolls</SelectLabel>
{atolls?.data.map((atoll) => (
{(atolls?.data ?? []).map((atoll) => (
<SelectItem key={atoll.id} value={atoll.id.toString()}>
{atoll.name}
</SelectItem>
+19
View File
@@ -29,6 +29,25 @@ apiClient.interceptors.request.use((config) => {
return config;
});
// Normalise non-JSON error pages. Django (DisallowedHost / DEBUG tracebacks),
// nginx (502/504), etc. return an HTML body on 4xx/5xx instead of the JSON
// envelope callers expect. Left as-is, the raw HTML string flows into consumers
// and crashes things like `atolls.data.map(...)`. Rewrite it into a JSON error
// body so `handleApiResponse` and action code read a clean `{ message, detail }`.
apiClient.interceptors.response.use((response) => {
const contentType = String(response.headers?.["content-type"] ?? "");
const isHtml = !contentType.includes("application/json");
if (response.status >= 400 && isHtml && typeof response.data === "string") {
const title = response.data.match(/<title>([\s\S]*?)<\/title>/i)?.[1]?.trim();
response.data = {
message: `Server error (${response.status})`,
detail:
title || `The server returned a non-JSON ${response.status} response.`,
};
}
return response;
});
// On 401 the token is dead — clear it and bounce to signin (once).
apiClient.interceptors.response.use((response) => {
if (response.status === 401) {
+6 -1
View File
@@ -1,12 +1,17 @@
import type { ApiResponse, Atoll } from "@/lib/backend-types";
import apiClient from "@/lib/api-client";
import { handleApiResponse } from "@/utils/tryCatch";
/**
* Atoll list (with nested islands) for the signup atoll/island dropdowns.
* The endpoint is paginated, so this returns the `{ meta, links, data }`
* envelope — consumers read `.data`.
*
* Runs through `handleApiResponse` so a 4xx/5xx (e.g. DisallowedHost 400)
* throws a clean error for React Query to surface, instead of returning a
* non-envelope body that crashes `atolls.data.map(...)`.
*/
export async function getAtolls() {
const response = await apiClient.get("/api/auth/atolls/");
return response.data as ApiResponse<Atoll>;
return handleApiResponse<ApiResponse<Atoll>>(response, "getAtolls");
}