diff --git a/src/app/api/ai/analyze/route.ts b/src/app/api/ai/analyze/route.ts
index d379861..89fc4af 100644
--- a/src/app/api/ai/analyze/route.ts
+++ b/src/app/api/ai/analyze/route.ts
@@ -37,7 +37,15 @@ export async function POST(req: NextRequest) {
console.warn(`[AI] Timeout for product analysis — OpenRouter too slow.`);
return NextResponse.json({ error: "timeout", retryAfter: 5 }, { status: 504 });
}
+
const msg = err instanceof Error ? err.message : "Unknown error";
+
+ // Propager l'état de surcharge Open Router (502 Gateway, 503 Unavailable, 529 Overloaded)
+ if (msg.includes("502") || msg.includes("503") || msg.includes("529") || msg.includes("Bad Gateway") || msg.includes("overloaded")) {
+ console.warn(`[AI] External API overload detected: ${msg}`);
+ return NextResponse.json({ error: "gateway_timeout", detail: msg }, { status: 502 });
+ }
+
return NextResponse.json({ error: msg }, { status: 500 });
}
}
diff --git a/src/features/ai-copilot/components/ai-insight-block.tsx b/src/features/ai-copilot/components/ai-insight-block.tsx
index 40a262a..2b00270 100644
--- a/src/features/ai-copilot/components/ai-insight-block.tsx
+++ b/src/features/ai-copilot/components/ai-insight-block.tsx
@@ -145,7 +145,10 @@ export function AiInsightBlock({ row }: AiInsightBlockProps) {
if (status === "error") {
return (
-
+
diff --git a/src/features/grid/components/bulk-ai-analyzer.tsx b/src/features/grid/components/bulk-ai-analyzer.tsx
index 769ca8c..296d8ad 100644
--- a/src/features/grid/components/bulk-ai-analyzer.tsx
+++ b/src/features/grid/components/bulk-ai-analyzer.tsx
@@ -227,12 +227,12 @@ export function BulkAiAnalyzer() {
const wait = (retryData.retryAfter ?? 30) * 1000;
console.warn(`[BulkAI] Rate limited, retry in ${wait / 1000}s`);
await new Promise((r) => setTimeout(r, Math.min(wait, 15_000)));
- } else if (res.status === 504) {
- // Timeout serveur : retry rapide (le modèle était peut-être surchargé)
- console.warn(`[BulkAI] Timeout (504) for ${payload.codein}, retry #${attempt + 1}`);
- await new Promise((r) => setTimeout(r, 2_000));
+ } else if (res.status === 504 || res.status === 502 || res.status === 503 || res.status === 529) {
+ // Timeout ou réseau surchargé : on tente de réessayer de suite
+ console.warn(`[BulkAI] Network issue (${res.status}) for ${payload.codein}, retry #${attempt + 1}`);
+ await new Promise((r) => setTimeout(r, 2_000 * (attempt + 1))); // Exponential backoff (2s, 4s, 6s)
} else {
- // Autre erreur (500, etc.) : ne pas réessayer inutilement
+ // Autre erreur (500 local, auth, etc.) : ne pas réessayer inutilement
break;
}
} catch (fetchErr) {
@@ -242,7 +242,18 @@ export function BulkAiAnalyzer() {
}
if (!res || !res.ok) {
- setError(payload.codein, res?.status === 504 ? "Timeout IA" : "Erreur API");
+ let errorMsg = res?.status === 504 ? "Timeout IA" : (res?.status === 502 ? "API Surchargée" : `Erreur HTTP ${res?.status}`);
+
+ // On tente d'extraire le message original s'il y en a un
+ if (res && res.headers.get("content-type")?.includes("application/json")) {
+ try {
+ const errData = await res.json();
+ if (errData.error) errorMsg += ` - ${errData.error}`;
+ if (errData.detail) errorMsg += ` (${errData.detail})`;
+ } catch (e) { /* ignore JSON parse error on error */ }
+ }
+
+ setError(payload.codein, errorMsg);
errorsCount++;
} else {
const data = await res.json();