diff --git a/src/core/ai/gateway.ts b/src/core/ai/gateway.ts index f6deb2e4c..fcdea1969 100644 --- a/src/core/ai/gateway.ts +++ b/src/core/ai/gateway.ts @@ -862,7 +862,10 @@ export function isTokenLimitError(err: unknown): boolean { return ( /max.*allowed.*tokens.*batch/i.test(msg) || /batch.*too.*many.*tokens/i.test(msg) || - /token.*limit.*exceeded/i.test(msg) + /token.*limit.*exceeded/i.test(msg) || + // OpenAI embeddings: "Invalid 'input': maximum request size is 300000 tokens per request." + /maximum request size.*tokens/i.test(msg) || + /max.*tokens.*per.*request/i.test(msg) ); } diff --git a/test/ai/adaptive-embed-batch.test.ts b/test/ai/adaptive-embed-batch.test.ts index 6cd8d06ab..11e05c863 100644 --- a/test/ai/adaptive-embed-batch.test.ts +++ b/test/ai/adaptive-embed-batch.test.ts @@ -147,6 +147,21 @@ describe('isTokenLimitError (pure helper)', () => { expect(isTokenLimitError(new Error('Batch contains too many tokens'))).toBe(true); }); + test('matches OpenAI embeddings "maximum request size" error (regression: PR ###)', () => { + // Real error string returned by OpenAI's /v1/embeddings endpoint when the + // sum of all input items exceeds 300k tokens. Without this match, gbrain's + // recursive-halving safety net never engages on OpenAI and the queue stalls + // forever on token-dense pages. + const openaiErr = new Error( + "Invalid 'input': maximum request size is 300000 tokens per request.", + ); + expect(isTokenLimitError(openaiErr)).toBe(true); + }); + + test('matches generic "max tokens per request" phrasing', () => { + expect(isTokenLimitError(new Error('Exceeded 300000 max tokens per request'))).toBe(true); + }); + test('does not match unrelated errors', () => { expect(isTokenLimitError(new Error('Connection refused'))).toBe(false); expect(isTokenLimitError(new Error('Invalid API key'))).toBe(false);