fix(project): surface API errors instead of hanging on Loading…
Adds a 10s timeout + AbortController to the codebases fetch and
parses error bodies defensively (so a non-JSON 4xx/5xx still shows
a status code instead of disappearing). The Product tab will now
show a clear message ("Request timed out", "HTTP 401 Unauthorized",
etc.) instead of spinning forever when the API can't respond.
Made-with: Cursor
This commit is contained in:
@@ -46,27 +46,50 @@ export default function ProductTab() {
|
||||
setReason(undefined);
|
||||
setSelectedFile(null);
|
||||
|
||||
fetch(`/api/projects/${projectId}/codebases`, { credentials: "include" })
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 10_000);
|
||||
|
||||
fetch(`/api/projects/${projectId}/codebases`, {
|
||||
credentials: "include",
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then(async r => {
|
||||
const data = (await r.json()) as CodebasesResponse;
|
||||
if (!r.ok) throw new Error(data.error || `HTTP ${r.status}`);
|
||||
return data;
|
||||
let body: CodebasesResponse | { error?: string } = {};
|
||||
try {
|
||||
body = await r.json();
|
||||
} catch {
|
||||
/* non-JSON body — fall through to status-only error */
|
||||
}
|
||||
if (!r.ok) {
|
||||
const msg = (body as { error?: string }).error || `HTTP ${r.status} ${r.statusText}`.trim();
|
||||
throw new Error(msg);
|
||||
}
|
||||
return body as CodebasesResponse;
|
||||
})
|
||||
.then(data => {
|
||||
if (cancelled) return;
|
||||
setCodebases(data.codebases);
|
||||
setCodebases(data.codebases ?? []);
|
||||
setReason(data.reason);
|
||||
// Auto-expand the first codebase so users see something
|
||||
if (data.codebases[0]) {
|
||||
if (data.codebases?.[0]) {
|
||||
setExpanded(new Set([data.codebases[0].id]));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (!cancelled) setListError(err.message || "Failed to load");
|
||||
if (cancelled) return;
|
||||
if (err?.name === "AbortError") {
|
||||
setListError("Request timed out after 10s.");
|
||||
} else {
|
||||
setListError(err?.message || "Failed to load codebases");
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
controller.abort();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, [projectId]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user