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

  1. 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.
  2. Verify with curl using the same URL, key, and model as the env vars.
  3. For 429s, set GITNEXUS_EMBEDDING_MIN_INTERVAL_MS to pace requests and/or reduce batch size.
  4. 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

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


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)