abhigyanpatwari/GitNexus · error · HttpEmbeddingError
Embedding endpoint returned
Error message
Embedding endpoint returned ${err.response.status} (${safeUrl(url)}, batch ${batchIndex}) What it means
httpEmbedBatch maps ResilientFetchExhaustedError to this message: the endpoint kept returning the same non-2xx HTTP status across all retry attempts (default from GITNEXUS_EMBEDDING_MAX_ATTEMPTS), so the final status is surfaced. Retryable statuses were already retried with backoff before this throws; the status code tells you which class of endpoint problem it is.
Solutions
- Read the status: 401/403 → fix GITNEXUS_EMBEDDING_API_KEY; 404 → fix URL path (add /v1) or model name; 400 → check model supports the configured dims; 429 → slow down or raise quota; 5xx → endpoint-side fix.
- Verify with curl using the same URL, key, and model as the env vars.
- For 429s, set GITNEXUS_EMBEDDING_MIN_INTERVAL_MS to pace requests and/or reduce batch size.
- Raise GITNEXUS_EMBEDDING_MAX_ATTEMPTS (≤20) only for genuinely transient 5xx/429 outages.
Example fix
# before export GITNEXUS_EMBEDDING_URL=https://api.example.com # after (status 404 -> missing /v1) export GITNEXUS_EMBEDDING_URL=https://api.example.com/v1 export GITNEXUS_EMBEDDING_MODEL=text-embedding-3-small export GITNEXUS_EMBEDDING_API_KEY=sk-...
Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(`${process.env.GITNEXUS_EMBEDDING_URL}/embeddings`, {
method: 'POST',
headers: { 'content-type': 'application/json', authorization: `Bearer ${process.env.GITNEXUS_EMBEDDING_API_KEY}` },
body: JSON.stringify({ model: process.env.GITNEXUS_EMBEDDING_MODEL, input: 'ping' }),
});
if (!res.ok) throw new Error(`endpoint precheck failed: ${res.status}`); Type guard
const isEndpointStatusError = (e: unknown): boolean =>
e instanceof Error && /Embedding endpoint returned \d{3}/.test(e.message); Try / catch
try {
vectors = await httpEmbed(texts);
} catch (e) {
if (isEndpointStatusError(e)) {
const status = Number(/returned (\d{3})/.exec(e.message)![1]);
if (status === 401 || status === 403) throw new Error('check GITNEXUS_EMBEDDING_API_KEY');
if (status === 404) throw new Error('check GITNEXUS_EMBEDDING_URL path and model name');
if (status === 429) { await sleep(backoffMs); return httpEmbed(texts); }
}
throw e;
} Prevention
- Smoke-test URL + key + model with curl whenever any of the three changes.
- Include /v1 in GITNEXUS_EMBEDDING_URL for OpenAI-compatible gateways.
- Pace requests (GITNEXUS_EMBEDDING_MIN_INTERVAL_MS) to stay under provider rate limits during full-repo runs.
When it happens
Trigger: 401/403 from a wrong or expired GITNEXUS_EMBEDDING_API_KEY; 404 from a wrong URL path or unknown GITNEXUS_EMBEDDING_MODEL; 400 from rejected request shape (bad model, unsupported dims); 429 or 5xx persisting beyond the retry budget.
Common situations: API key rotated but env not updated, model deprecation/renaming on the provider, hitting a free-tier rate limit (429) during a full-repo embedding run, or a gateway returning 502 while the backend is down.
Related errors
- Embedding request failed
- after attempt(s) ( , batch )
- err.terminalMessage (terminal 2xx body error)
- Embedding endpoint circuit open
- Embedding endpoint returned an unexpected response shape
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-08-20).
Data as JSON: /api/errors/008c09834c19d9f1.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/embeddings/http-client.ts:574
throw new HttpEmbeddingError(
`${err.message} after ${maxAttempts} attempt(s) (${safeUrl(url)}, batch ${batchIndex})`,
{ cause: err.cause },
);
}
if (err instanceof CircuitOpenError) {
throw new HttpEmbeddingError(
`Embedding endpoint circuit open (${safeUrl(url)}, batch ${batchIndex}): retry in ${Math.ceil(err.retryAfterMs / 1000)}s`,
{ cause: err },
);
}
if (err instanceof DOMException && err.name === 'TimeoutError') {
throw new HttpEmbeddingError(
`Embedding request timed out after ${timeoutMs}ms (${safeUrl(url)}, batch ${batchIndex})`,
{ cause: err },
);
}
if (err instanceof ResilientFetchExhaustedError) {
throw new HttpEmbeddingError(
`Embedding endpoint returned ${err.response.status} (${safeUrl(url)}, batch ${batchIndex})`,
{ cause: err },
);
}
const reason = sanitizeReason(err instanceof Error ? err.message : String(err), url, apiKey);
const safeCause = new Error(reason);
safeCause.name = err instanceof Error ? err.name : 'EmbeddingTransportError';
throw new HttpEmbeddingError(
`Embedding request failed (${safeUrl(url)}, batch ${batchIndex}): ${reason}`,
{ cause: safeCause },
);
}
if (!resp.ok) {
// resilientFetch already retried 5xx/429; any non-OK response here is
// a terminal client error (4xx other than 429).
throw new HttpEmbeddingError(
`Embedding endpoint returned ${resp.status} (${safeUrl(url)}, batch ${batchIndex})`,View on GitHub (pinned to ac9a4e9abd)