Skip to content

Commit 4a752ea

Browse files
committed
fix: wrap backend errors in Anthropic format to prevent login page
When the backend returns 4xx/5xx errors, Claude Code doesn't understand non-Anthropic error shapes and falls back to showing its login page. Now intercepts error responses and wraps them in { type: 'error', error: { type, message } } format.
1 parent 9572a7f commit 4a752ea

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

src/proxy/server.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,44 @@ export function createProxy(options: ProxyOptions): http.Server {
413413
response.headers.forEach((v, k) => {
414414
responseHeaders[k] = v;
415415
});
416+
417+
// Intercept error responses and ensure Anthropic-format errors
418+
// so Claude Code doesn't fall back to showing a login page
419+
if (response.status >= 400 && !responseHeaders['content-type']?.includes('text/event-stream')) {
420+
let errorBody: string;
421+
try {
422+
const rawText = await response.text();
423+
const parsed = JSON.parse(rawText);
424+
// Already has Anthropic error shape? Pass through
425+
if (parsed.type === 'error' && parsed.error) {
426+
errorBody = rawText;
427+
} else {
428+
// Wrap in Anthropic error format
429+
const errorMsg = parsed.error?.message || parsed.message || rawText.slice(0, 500);
430+
errorBody = JSON.stringify({
431+
type: 'error',
432+
error: {
433+
type: response.status === 401 ? 'authentication_error'
434+
: response.status === 402 ? 'invalid_request_error'
435+
: response.status === 429 ? 'rate_limit_error'
436+
: response.status === 400 ? 'invalid_request_error'
437+
: 'api_error',
438+
message: `[${finalModel}] ${errorMsg}`,
439+
},
440+
});
441+
}
442+
} catch {
443+
errorBody = JSON.stringify({
444+
type: 'error',
445+
error: { type: 'api_error', message: `Backend returned ${response.status}` },
446+
});
447+
}
448+
res.writeHead(response.status, { 'Content-Type': 'application/json' });
449+
res.end(errorBody);
450+
log(`⚠️ ${response.status} from backend for ${finalModel}`);
451+
return;
452+
}
453+
416454
res.writeHead(response.status, responseHeaders);
417455

418456
const isStreaming =

0 commit comments

Comments
 (0)