diff --git a/apps/sim/lib/embeddings/client.test.ts b/apps/sim/lib/embeddings/client.test.ts index 78ce526bce9..4f7d27d9a1e 100644 --- a/apps/sim/lib/embeddings/client.test.ts +++ b/apps/sim/lib/embeddings/client.test.ts @@ -823,11 +823,8 @@ describe('knowledge embedding transport fallback', () => { }) /** - * OpenAI returns 429 for an exhausted balance as well as for a rate limit, but - * only one of them reopens. Retrying a spent account cannot succeed, and since - * the sweep re-queues failed documents every sync it turns into permanent load - * — this was observed burning every attempt on thousands of documents for - * weeks against an account with no credit. + * A spent account never reopens, and the sweep re-queues failed documents every + * sync — so retrying one burns the budget per document, indefinitely. */ it('does not retry a 429 that reports an exhausted balance', async () => { vi.useFakeTimers() diff --git a/apps/sim/lib/embeddings/client.ts b/apps/sim/lib/embeddings/client.ts index 9e39a691225..825f96d8b6c 100644 --- a/apps/sim/lib/embeddings/client.ts +++ b/apps/sim/lib/embeddings/client.ts @@ -79,10 +79,7 @@ const EMBEDDING_RETRY_BUDGET_MS = EMBEDDING_MAX_RETRIES * EMBEDDING_MAX_RETRY_DE export class EmbeddingAPIError extends Error { public status: number - /** - * The provider rejected this for an exhausted balance rather than a rate that - * will recover. Both arrive as 429. - */ + /** Rejected for an exhausted balance rather than a recoverable rate. Both are 429. */ public quotaExhausted?: boolean /** @@ -100,13 +97,8 @@ export class EmbeddingAPIError extends Error { /** * True when a rejection body reports an exhausted balance rather than a rate - * limit. - * - * OpenAI returns 429 for both, but only one of them reopens. `insufficient_quota` - * stands until somebody adds credit, so retrying it cannot succeed no matter how - * long the loop waits — and because a failed document is re-queued by the sweep - * on every sync, an account that has run out turns into a permanent load: the - * budget is spent per document, per attempt, forever. + * limit. OpenAI returns 429 for both, but only a rate limit reopens: a spent + * account stands until someone adds credit, so retrying it cannot succeed. */ function isQuotaExhaustionBody(errorText: string): boolean { try { @@ -148,13 +140,10 @@ function statedWaitOutlastsBudget(error: unknown): boolean { } /** - * Whether another attempt against the same provider could plausibly succeed. - * - * Deliberately narrower than {@link isTransientEmbeddingError}, which also - * decides whether the fallback chain should try a *different* provider. Those - * two questions differ: an exhausted balance rules out the key we just used, but - * says nothing about the next one in the chain, so a quota rejection stops the - * retries here while remaining eligible for failover. + * Whether another attempt against the *same* provider could succeed. Narrower + * than {@link isTransientEmbeddingError}, which decides whether to fail over to a + * different one: an exhausted balance rules out the key just used but says + * nothing about the next in the chain. */ function isWorthRetrying(error: unknown): boolean { if (!isTransientEmbeddingError(error)) return false