Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit c5eb84b

Browse files
author
Roo Code
committed
fix(embeddings): add timeouts, 5xx retry, and proper error messages for OpenAI Compatible embedder
Fix critical issues where the OpenAI Compatible Embedder would hang indefinitely on unresponsive servers and not retry 5xx server errors. Changes: - Add 60s timeout to OpenAI SDK constructor (timeout: 60000, maxRetries: 0) - Add AbortController with 60s timeout to makeDirectEmbeddingRequest() - Convert AbortError to HTTP 504 (Gateway Timeout) - Extend retry logic to handle 5xx errors (500-599) with exponential backoff - Update validation error messages: - 429 -> rateLimitExceeded - 502 -> badGateway (new) - 503 -> serviceUnavailable - 504 -> gatewayTimeout (new) - Other 5xx -> serverError (was configurationError) - Add i18n translations for new error messages in 17 languages - Add unit tests for timeout handling and 5xx retry (5 new tests) - Add unit tests for getErrorMessageForStatus (10 new tests) Impact: - All OpenAI-compatible embedders benefit (Gemini, Mistral, VercelAiGateway, OpenRouter) - No breaking changes - existing functionality preserved - Prevents infinite waits on unresponsive embedding servers - Clear error messages for 502/503/504 errors Files changed: 21 - 2 source files (openai-compatible.ts, validation-helpers.ts) - 17 i18n locale files (en, ru, de, es, fr, hi, id, it, ja, ko, nl, pl, pt-BR, tr, vi, zh-CN, zh-TW) - 3 test files (openai-compatible.spec.ts, openai.spec.ts, validation-helpers.spec.ts) Test results: - code-index tests: 482 passed, 0 failed - All project tests: 8210 total (8154 passed, 57 skipped, 0 failed) - Test files: 582 (569 run, 13 skipped) - Duration: 4m44s
1 parent 137d3f4 commit c5eb84b

23 files changed

Lines changed: 517 additions & 82 deletions

IMPLEMENTATION-REPORT.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Implementation Report: Embedding Indexing Fix
2+
3+
## Summary
4+
5+
Fixed critical issues in the OpenAI Compatible Embedder that caused HTTP 503 errors and infinite waits during codebase indexing. The fix adds timeouts, retry logic for 5xx server errors, and proper error messages.
6+
7+
## Problem
8+
9+
When indexing codebase through OpenAI-compatible API (`http://0.0.0.0:11434/v1`), the following error occurred:
10+
11+
```
12+
Indexing partially failed: Only 780 of 2834 blocks were indexed.
13+
Failed to process batch after 3 attempts:
14+
Failed to create embeddings after 3 attempts: HTTP 503 - 503 status code (no body)
15+
```
16+
17+
**Root Cause:** The OpenAI Compatible Embedder lacked timeouts and did not retry 5xx errors. The server could hang indefinitely — the program needed to handle such situations correctly.
18+
19+
## Changes Made
20+
21+
### 1. Core Code Changes
22+
23+
#### `src/services/code-index/embedders/openai-compatible.ts`
24+
25+
- **Added timeout constants:** `OPENAI_COMPATIBLE_EMBEDDING_TIMEOUT_MS = 60000` (60s), `OPENAI_COMPATIBLE_VALIDATION_TIMEOUT_MS = 30000` (30s)
26+
- **OpenAI SDK constructor:** Added `timeout: 60000` and `maxRetries: 0` (disabled built-in retry to use our own logic)
27+
- **AbortController in fetch:** Added `AbortController` with 60s timeout to `makeDirectEmbeddingRequest()`, converts `AbortError` to HTTP 504 (Gateway Timeout)
28+
- **Retry for 5xx errors:** Extended retry logic in `_embedBatchWithRetries()` to handle both 429 (rate limit) and 500-599 (server errors) with exponential backoff
29+
30+
#### `src/services/code-index/shared/validation-helpers.ts`
31+
32+
- **Updated `getErrorMessageForStatus()`:**
33+
- 429 → `rateLimitExceeded` (was `serviceUnavailable`)
34+
- 502 → `badGateway` (new)
35+
- 503 → `serviceUnavailable` (reused)
36+
- 504 → `gatewayTimeout` (new)
37+
- Other 5xx → `serverError` (was `configurationError`)
38+
39+
### 2. Localization (17 files)
40+
41+
Added 5 new i18n keys to `validation` section and 1 new key `serverErrorRetry` to root in all 17 locale files:
42+
43+
| Language | File |
44+
| --------------------- | ---------------------------------------- |
45+
| English | `src/i18n/locales/en/embeddings.json` |
46+
| Russian | `src/i18n/locales/ru/embeddings.json` |
47+
| German | `src/i18n/locales/de/embeddings.json` |
48+
| Spanish | `src/i18n/locales/es/embeddings.json` |
49+
| French | `src/i18n/locales/fr/embeddings.json` |
50+
| Hindi | `src/i18n/locales/hi/embeddings.json` |
51+
| Indonesian | `src/i18n/locales/id/embeddings.json` |
52+
| Italian | `src/i18n/locales/it/embeddings.json` |
53+
| Japanese | `src/i18n/locales/ja/embeddings.json` |
54+
| Korean | `src/i18n/locales/ko/embeddings.json` |
55+
| Dutch | `src/i18n/locales/nl/embeddings.json` |
56+
| Polish | `src/i18n/locales/pl/embeddings.json` |
57+
| Portuguese (BR) | `src/i18n/locales/pt-BR/embeddings.json` |
58+
| Turkish | `src/i18n/locales/tr/embeddings.json` |
59+
| Vietnamese | `src/i18n/locales/vi/embeddings.json` |
60+
| Chinese (Simplified) | `src/i18n/locales/zh-CN/embeddings.json` |
61+
| Chinese (Traditional) | `src/i18n/locales/zh-TW/embeddings.json` |
62+
63+
### 3. Tests
64+
65+
#### `src/services/code-index/embedders/__tests__/openai-compatible.spec.ts`
66+
67+
- Updated existing test: 500 error now retries 3 times (was 1)
68+
- Added `timeout handling` describe block with 2 tests
69+
- Added `5xx retry handling` describe block with 3 tests (502, 503, 504)
70+
71+
#### `src/services/code-index/embedders/__tests__/openai.spec.ts`
72+
73+
- Fixed regression: Updated test expectations for new timeout/maxRetries parameters
74+
75+
#### `src/services/code-index/shared/__tests__/validation-helpers.spec.ts`
76+
77+
- Added `getErrorMessageForStatus` describe block with 10 tests covering all HTTP status codes
78+
79+
## Test Results
80+
81+
- **21 test files** — all passed
82+
- **482 tests** — 0 failed, 0 errors, 0 warnings
83+
- **Duration:** ~9-11s
84+
85+
## Files Changed (21 total)
86+
87+
| File | Changes |
88+
| ----------------------------------------------------------------------- | ----------------------------------------------- |
89+
| `src/services/code-index/embedders/openai-compatible.ts` | Steps 1-4: Timeouts, AbortController, 5xx retry |
90+
| `src/services/code-index/shared/validation-helpers.ts` | Step 5: 5xx error messages |
91+
| `src/i18n/locales/*/embeddings.json` (17 files) | Step 6: i18n keys |
92+
| `src/services/code-index/embedders/__tests__/openai-compatible.spec.ts` | Steps 7-8: New tests |
93+
| `src/services/code-index/embedders/__tests__/openai.spec.ts` | Regression fix |
94+
| `src/services/code-index/shared/__tests__/validation-helpers.spec.ts` | Step 9: New tests |
95+
96+
## Architecture
97+
98+
```
99+
Request → {Full URL?} → Yes → makeDirectEmbeddingRequest (AbortController 60s)
100+
→ No → OpenAI SDK (timeout 60s, maxRetries 0)
101+
102+
Error? → {429 or 5xx?} → Yes → Retry with exponential backoff
103+
→ No → Throw immediately
104+
```
105+
106+
## Impact
107+
108+
- **All OpenAI-compatible embedders benefit:** Gemini, Mistral, VercelAiGateway, OpenRouter
109+
- **No breaking changes:** Existing functionality preserved
110+
- **Better user experience:** Clear error messages for 502/503/504 errors
111+
- **Prevents infinite waits:** 60s timeout on all embedding requests

src/i18n/locales/de/embeddings.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/en/embeddings.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"failedMaxAttempts": "Failed to create embeddings after {{attempts}} attempts",
77
"textExceedsTokenLimit": "Text at index {{index}} exceeds maximum token limit ({{itemTokens}} > {{maxTokens}}). Skipping.",
88
"rateLimitRetry": "Rate limit hit, retrying in {{delayMs}}ms (attempt {{attempt}}/{{maxRetries}})",
9+
"serverErrorRetry": "Server error ({{status}}), retrying in {{delayMs}}ms (attempt {{attempt}}/{{maxRetries}})",
910
"ollama": {
1011
"couldNotReadErrorBody": "Could not read error body",
1112
"requestFailed": "Ollama API request failed with status {{status}} {{statusText}}: {{errorBody}}",
@@ -37,7 +38,11 @@
3738
"connectionFailed": "Failed to connect to the embedder service. Please check your connection settings and ensure the service is running.",
3839
"modelNotAvailable": "The specified model is not available. Please check your model configuration.",
3940
"configurationError": "Invalid embedder configuration. Please review your settings.",
40-
"serviceUnavailable": "The embedder service is not available. Please ensure it is running and accessible.",
41+
"serviceUnavailable": "Embedding service temporarily unavailable. Please try again later.",
42+
"rateLimitExceeded": "Rate limit exceeded. Please try again later.",
43+
"badGateway": "Bad gateway error from embedder service. The server received an invalid response.",
44+
"gatewayTimeout": "Gateway timeout error. The embedder service did not respond in time.",
45+
"serverError": "Server error from embedder service. Please try again later.",
4146
"invalidEndpoint": "Invalid API endpoint. Please check your URL configuration.",
4247
"invalidEmbedderConfig": "Invalid embedder configuration. Please check your settings.",
4348
"invalidApiKey": "Invalid API key. Please check your API key configuration.",

src/i18n/locales/es/embeddings.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/fr/embeddings.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/hi/embeddings.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/i18n/locales/id/embeddings.json

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)