abhigyanpatwari/GitNexus · error · HttpEmbeddingError
err.terminalMessage (terminal 2xx body error)
Error message
err.terminalMessage (terminal 2xx body error)
What it means
httpEmbedBatch retries requests whose 2xx body cannot be parsed/validated (RetryableEmbeddingBodyError). When retries are exhausted, it throws HttpEmbeddingError whose message is err.terminalMessage — a sanitized sentinel message — with the underlying parse error preserved only in cause. This deliberately keeps raw body text out of the top-level message so it cannot leak to stderr via sanitizeReason fallbacks.
Solutions
- Inspect err.cause — it holds the real parse error showing what the body actually looked like structurally.
- Verify the endpoint URL actually serves the embedding API and not a proxy/login page (curl the URL).
- Check the embedding server version matches the client's expected response schema; upgrade or reconfigure.
- Confirm the server is healthy; a 200-with-HTML usually means a gateway misroute.
Example fix
// before: URL points at a gateway root const url = 'https://gw.internal/'; // after: full embedding API path const url = 'https://gw.internal/embeddings/v1/embed';
Defensive patterns
Strategy: try-catch
Validate before calling
// verify the endpoint returns JSON embedding responses before batch use
const probe = await fetch(url, { method: 'POST', headers });
const ct = probe.headers.get('content-type') ?? '';
if (!ct.includes('application/json')) throw new Error(`EMBED_URL returns ${ct}; expected JSON`); Try / catch
try {
vectors = await httpEmbedBatch(items, opts);
} catch (e) {
if (e instanceof HttpEmbeddingError && e.cause) {
console.error('Embedding body parse failed; underlying:', e.cause); // body shape info in cause
}
throw e;
} Prevention
- Curl the endpoint once and confirm it returns the expected JSON embedding schema.
- Point EMBED_URL at the embedding API route, not a gateway root or login page.
- Version-check the embedding server against the client's expected response schema.
- Alert on non-JSON content-types from the endpoint in monitoring.
When it happens
Trigger: Calling the HTTP embedding client against an endpoint that returns HTTP 200 with a body that is not the expected embedding JSON (HTML error page, proxy interstitial, wrong schema) on every attempt until maxAttempts is reached.
Common situations: Reverse proxy or API gateway returning an HTML login/error page with status 200; embedding server version returning a different response schema; misconfigured EMBED_URL pointing at a non-embedding service.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- Embedding endpoint returned
- Embedding request failed
- after attempt(s) ( , batch )
- Embedding endpoint circuit open
- Embedding endpoint returned an unexpected response shape
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/87885add4659669d.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/core/embeddings/http-client.ts:553
sleep: (ms) => abortableSleep(ms, requestOptions.signal),
},
},
);
} catch (err) {
if (
requestOptions.signal?.aborted ||
(err instanceof DOMException && err.name === 'AbortError')
) {
throw new HttpEmbeddingError(
`Embedding request cancelled (${safeUrl(url)}, batch ${batchIndex})`,
{ cause: err },
);
}
// Retries are exhausted on a bad 2xx body. Surface the message the sentinel
// carried, keeping the underlying parse error in `cause` only — the body
// text must never reach the `sanitizeReason` fallback and leak to stderr.
if (err instanceof RetryableEmbeddingBodyError) {
throw new HttpEmbeddingError(err.terminalMessage, { cause: err.cause });
}
if (err instanceof RetryableEmbeddingTimeoutError) {
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 },
);View on GitHub (pinned to ac9a4e9abd)