{"record":{"id":"966eebbf79e63930","repo":"abhigyanpatwari/GitNexus","slug":"hf-circuit-open-huggingface-download-circuit-is-o","errorCode":null,"errorMessage":"hf-circuit-open: HuggingFace download circuit is open after repeated network failures — will reset in ~${secsUntilReset}s","messagePattern":"hf-circuit-open: HuggingFace download circuit is open after repeated network failures — will reset in ~(.+?)s","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/embeddings/hf-env.ts","lineNumber":249,"sourceCode":"      ? Math.min(envTimeout, HF_MAX_TIMEOUT_MS)\n      : HF_DOWNLOAD_TIMEOUT_MS;\n  const resolvedMaxAttempts =\n    Number.isFinite(envMaxAttempts) && envMaxAttempts > 0\n      ? Math.min(Math.floor(envMaxAttempts), HF_MAX_ATTEMPTS_CAP)\n      : HF_MAX_ATTEMPTS;\n  const {\n    maxAttempts = resolvedMaxAttempts,\n    baseDelayMs = HF_BASE_DELAY_MS,\n    timeoutMs = resolvedTimeout,\n    circuit = hfDownloadCircuit,\n    onRetry,\n  } = options;\n  if (circuit.getState() === 'open') {\n    // Compute remaining cooldown without consuming a probe permit.\n    const openedAt = circuit.getOpenedAt();\n    const secsUntilReset =\n      openedAt !== null ? Math.ceil((circuit.getCooldownMs() - (Date.now() - openedAt)) / 1000) : 0;\n    throw new Error(\n      `${CIRCUIT_OPEN_TAG}: HuggingFace download circuit is open after repeated network failures` +\n        (secsUntilReset > 0 ? ` — will reset in ~${secsUntilReset}s` : ''),\n    );\n  }\n\n  // Retry budget delegated to `withRetry` from gitnexus-shared. The\n  // HF-specific bits — per-attempt timeout, network-vs-non-network\n  // classification, circuit-breaker recording, onRetry callback — wire\n  // through the `isRetryable` callback. `circuitTripped` is the\n  // sentinel that lets us replace the final thrown error with a\n  // CIRCUIT_OPEN_TAG message when the breaker tripped mid-loop.\n  let circuitTripped = false;\n\n  try {\n    return await withRetry(\n      async () => {\n        const result = await withDownloadTimeout(fn, timeoutMs);\n        circuit.recordSuccess();","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/embeddings/hf-env.ts#L231-L267","documentation":"Thrown by withHfDownloadRetry() at entry when the module-level HuggingFace download circuit breaker (hfDownloadCircuit) is already in the 'open' state. The breaker opens after CB_FAILURE_THRESHOLD (3) consecutive network failures and stays open for CB_RESET_TIMEOUT_MS (60s); while open, every call fails immediately without consuming a probe permit, computing the remaining cooldown from getOpenedAt() so the user knows how long to wait. This prevents stampeding huggingface.co during an outage.","triggerScenarios":"A second or subsequent model-download attempt within 60s of three consecutive network failures in the same process. The first trip throws error 114 (the trip itself); subsequent calls during the cooldown throw this 113 variant with the reset countdown.","commonSituations":"Retrying `analyze --embeddings` immediately after a network failure; a long-running MCP server that keeps attempting downloads while HF is unreachable; multiple parallel analyze processes in one process tripping the breaker then retrying.","solutions":["Wait until the stated cooldown (~60s) elapses, then retry.","Set HF_ENDPOINT to a reachable mirror (e.g. https://hf-mirror.com) and retry.","Fix the underlying network issue (proxy, DNS, firewall) so the breaker can close on a successful probe.","Route embeddings over HTTP via GITNEXUS_EMBEDDING_URL to avoid HuggingFace downloads entirely."],"exampleFix":"# before — breaker open, immediate retry fails again\n$ npx gitnexus analyze --embeddings  # fails\n$ npx gitnexus analyze --embeddings  # hf-circuit-open\n# after — wait for cooldown, use a mirror\n$ HF_ENDPOINT=https://hf-mirror.com npx gitnexus analyze --embeddings","handlingStrategy":"retry","validationCode":"import { hfDownloadCircuit } from 'gitnexus/src/core/embeddings/hf-env.js';\n// Check the breaker state before attempting a download.\nif (hfDownloadCircuit.getState() === 'open') {\n  console.warn('HF download circuit open — wait for cooldown or set HF_ENDPOINT to a mirror.');\n}","typeGuard":"import { isHfCircuitOpenError } from 'gitnexus/src/core/embeddings/hf-env.js';\nconst isCircuitOpen = (msg: string): boolean => isHfCircuitOpenError(msg);","tryCatchPattern":"import { isHfCircuitOpenError } from 'gitnexus/src/core/embeddings/hf-env.js';\ntry {\n  await initEmbedder();\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (isHfCircuitOpenError(msg)) {\n    // Wait for the stated cooldown, or switch to a mirror / HTTP embedding mode.\n    console.warn(msg);\n    process.env.HF_ENDPOINT = 'https://hf-mirror.com';\n    await initEmbedder();\n  } else throw err;\n}","preventionTips":["Set HF_ENDPOINT to a reachable mirror to keep the breaker closed.","Do not retry-in-a-tight-loop after a circuit open — respect the ~60s cooldown.","Use GITNEXUS_EMBEDDING_URL to bypass the HF download path entirely."],"tags":["network","circuit-breaker","huggingface","model-download","resilience"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}