{"record":{"id":"b750d553eaf69212","repo":"abhigyanpatwari/GitNexus","slug":"embedding-request-failed-safeurl-url-batch","errorCode":null,"errorMessage":"Embedding request failed (${safeUrl(url)}, batch ${batchIndex}): ${reason}","messagePattern":"Embedding request failed \\((.+?), batch (.+?)\\): (.+?)","errorType":"exception","errorClass":"HttpEmbeddingError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/embeddings/http-client.ts","lineNumber":582,"sourceCode":"        { cause: err },\n      );\n    }\n    if (err instanceof DOMException && err.name === 'TimeoutError') {\n      throw new HttpEmbeddingError(\n        `Embedding request timed out after ${timeoutMs}ms (${safeUrl(url)}, batch ${batchIndex})`,\n        { cause: err },\n      );\n    }\n    if (err instanceof ResilientFetchExhaustedError) {\n      throw new HttpEmbeddingError(\n        `Embedding endpoint returned ${err.response.status} (${safeUrl(url)}, batch ${batchIndex})`,\n        { cause: err },\n      );\n    }\n    const reason = sanitizeReason(err instanceof Error ? err.message : String(err), url, apiKey);\n    const safeCause = new Error(reason);\n    safeCause.name = err instanceof Error ? err.name : 'EmbeddingTransportError';\n    throw new HttpEmbeddingError(\n      `Embedding request failed (${safeUrl(url)}, batch ${batchIndex}): ${reason}`,\n      { cause: safeCause },\n    );\n  }\n\n  if (!resp.ok) {\n    // resilientFetch already retried 5xx/429; any non-OK response here is\n    // a terminal client error (4xx other than 429).\n    throw new HttpEmbeddingError(\n      `Embedding endpoint returned ${resp.status} (${safeUrl(url)}, batch ${batchIndex})`,\n    );\n  }\n\n  if (parsed === undefined) {\n    // Defensively unreachable: an OK response either sets `parsed` or throws\n    // out of `fetchImpl`. Kept so the narrowing holds without a non-null\n    // assertion, and so a future `resilientFetch` change can't return an\n    // unvalidated body silently.","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/core/embeddings/http-client.ts#L564-L600","documentation":"Thrown as HttpEmbeddingError when a batched POST to <GITNEXUS_EMBEDDING_URL>/embeddings fails at the transport layer (DNS failure, connection refused, TLS error, timeout, or aborted request). resilientFetch has already exhausted its retry budget (5xx/429 with capped backoff), so this error means the endpoint could not be reached successfully at all. The reason string is sanitized (sanitizeReason strips API keys) and the URL is redacted via safeUrl, so the message is safe to log.","triggerScenarios":"Calling httpEmbed() or httpEmbedBatch() while GITNEXUS_EMBEDDING_URL points to an unreachable host (typo in hostname, DNS not resolving), the embedding server is down, a proxy/firewall blocks the egress, the TLS certificate is invalid, or the per-request timeout (GITNEXUS_EMBEDDING_TIMEOUT_MS) is exceeded on every attempt. Also triggered when GITNEXUS_EMBEDDING_MAX_ATTEMPTS retries are all consumed by network resets.","commonSituations":"Running `gitnexus analyze` on a laptop with a corporate proxy that intercepts HTTPS; pointing GITNEXUS_EMBEDDING_URL at a localhost Ollama/LM Studio instance that is not started; using an internal DNS name that only resolves inside the VPN; a self-signed certificate on a private vLLM endpoint.","solutions":["Verify the endpoint is reachable from the same machine: curl -sS -o /dev/null -w '%{http_code}' \"$GITNEXUS_EMBEDDING_URL/embeddings\" (expect 4xx, not 000).","Check for typos in GITNEXUS_EMBEDDING_URL (no scheme, wrong port, trailing garbage); the code appends /embeddings itself, so supply only the base URL such as http://localhost:11434/v1.","If behind a proxy or VPN, make sure HTTPS_PROXY/HTTP_PROXY or DNS resolution works for the embedding host, or start the local embedding server (e.g. ollama serve).","For slow endpoints, raise the timeout env var and retry budget before concluding the host is down.","If embeddings are optional, unset GITNEXUS_EMBEDDING_URL and GITNEXUS_EMBEDDING_MODEL to fall back to the local ONNX embedder instead of the HTTP backend."],"exampleFix":"# before\nexport GITNEXUS_EMBEDDING_URL=http://locahost:11434/v1   # typo: locahost\nexport GITNEXUS_EMBEDDING_MODEL=nomic-embed-text\ngitnexus analyze  # -> Embedding request failed (http://locahost..., batch 0): ...\n\n# after\nexport GITNEXUS_EMBEDDING_URL=http://localhost:11434/v1\ngitnexus analyze","handlingStrategy":"try-catch","validationCode":"// Fail fast before a long analyze run: probe the embedding endpoint.\nimport { isHttpMode } from './core/embeddings/http-client.js';\n\nexport async function assertEmbeddingEndpointReachable(): Promise<void> {\n  if (!isHttpMode()) return;\n  const base = process.env.GITNEXUS_EMBEDDING_URL!.replace(/\\/+$/, '');\n  const res = await fetch(`${base}/embeddings`, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json' },\n    body: JSON.stringify({\n      model: process.env.GITNEXUS_EMBEDDING_MODEL,\n      input: ['ping'],\n    }),\n    signal: AbortSignal.timeout(10_000),\n  }).catch((err) => {\n    throw new Error(`embedding endpoint unreachable: ${base} (${err.message})`);\n  });\n  if (res.status >= 500 || res.status === 429) {\n    throw new Error(`embedding endpoint unhealthy: ${res.status}`);\n  }\n}","typeGuard":"import { HttpEmbeddingError } from './core/embeddings/http-client.js';\n\nexport const isHttpEmbeddingError = (e: unknown): e is HttpEmbeddingError =>\n  e instanceof HttpEmbeddingError;","tryCatchPattern":"try {\n  vectors = await httpEmbed(texts);\n} catch (err) {\n  if (isHttpEmbeddingError(err) && err.message.startsWith('Embedding request failed')) {\n    // Transport-level failure; internal retries already exhausted by resilientFetch.\n    // Log sanitized message (URL/api key already redacted) and surface a fix hint.\n    throw new Error(\n      `${err.message} — check GITNEXUS_EMBEDDING_URL reachability, proxy/DNS, ` +\n      'and GITNEXUS_EMBEDDING_TIMEOUT_MS',\n      { cause: err },\n    );\n  }\n  throw err;\n}","preventionTips":["Verify the endpoint with a one-line curl POST to $GITNEXUS_EMBEDDING_URL/embeddings before starting analyze.","Run a reachability probe (like the validationCode above) at pipeline startup so a dead endpoint fails in seconds, not mid-batch.","For local servers (Ollama, vLLM), add a healthcheck to the wrapper script that starts them before gitnexus.","Keep GITNEXUS_EMBEDDING_MAX_ATTEMPTS and the timeout env vars sized for your endpoint's latency to survive transient blips."],"tags":["network","embeddings","http","retry-exhausted","configuration"],"backgroundTag":"http-request-failed","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}