{"record":{"id":"2d7df13e1ec4b89f","repo":"Panniantong/Agent-Reach","slug":"provider-network-error-e","errorCode":null,"errorMessage":"{provider}: network error: {e}","messagePattern":"(.+?): network error: (.+?)","errorType":"exception","errorClass":"TranscribeError","httpStatus":null,"severity":"error","filePath":"agent_reach/transcribe.py","lineNumber":390,"sourceCode":"    key = _provider_key(provider, cfg)\n    if not key:\n        raise NoProviderConfigured(\n            f\"{provider}: missing {PROVIDERS[provider]['key_field']} \"\n            f\"(configure with `agent-reach configure {provider}-key ...`)\"\n        )\n\n    info = PROVIDERS[provider]\n    with chunk.open(\"rb\") as fh:\n        try:\n            resp = requests.post(\n                info[\"endpoint\"],\n                headers={\"Authorization\": f\"Bearer {key}\"},\n                files={\"file\": (chunk.name, fh, \"audio/m4a\")},\n                data={\"model\": info[\"model\"], \"response_format\": \"text\"},\n                timeout=timeout,\n            )\n        except requests.RequestException as e:\n            raise TranscribeError(f\"{provider}: network error: {e}\") from e\n\n    if not resp.ok:\n        raise TranscribeError(f\"{provider}: HTTP {resp.status_code}: {resp.text[:300]}\")\n    return resp.text\n\n\ndef _provider_order(provider: str) -> List[str]:\n    if provider == \"auto\":\n        return [\"groq\", \"openai\"]\n    if provider in PROVIDERS:\n        return [provider]\n    raise TranscribeError(f\"unknown provider: {provider} (use groq|openai|auto)\")\n\n\ndef transcribe(\n    source: str,\n    *,\n    provider: str = \"auto\",","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/Panniantong/Agent-Reach/blob/93ae1d18c37b707dec053c7c4f9d91cd8ef8943d/agent_reach/transcribe.py#L372-L408","documentation":"Raised by transcribe_chunk (transcribe.py:389-390) when the requests.post to the provider endpoint throws requests.RequestException — connection failures, DNS errors, TLS problems, or the 120s default request timeout (requests.Timeout is a RequestException subclass). The original exception is chained via `from e`.","triggerScenarios":"transcribe_chunk with default timeout=120 on a chunk upload that stalls (large chunk + slow uplink); DNS failure reaching api.groq.com/api.openai.com; corporate proxy intercepting TLS; connection reset by the provider edge.","commonSituations":"Uploading from bandwidth-constrained environments (10-min chunk at ~2.4 MB usually fits, but a fallback path sending an unsplit 24 MB compressed file can be slow); egress-firewalled containers missing proxy env vars; transient provider-side resets.","solutions":["Retry with backoff — most occurrences are transient; wrap the call or enable provider='auto' + allow_provider_fallback=True in transcribe()","If timeouts recur, pass a larger timeout: transcribe_chunk(chunk, 'groq', timeout=300)","Check egress: curl -v https://api.groq.com/openai/v1/audio/transcriptions and proxy env (HTTPS_PROXY) in containers","Verify DNS resolves: getent hosts api.groq.com"],"exampleFix":"# before\ntext = transcribe_chunk(chunk, \"groq\")  # groq: network error: ...\n\n# after: bounded retry with a longer upload window\nimport time\nfor attempt in range(3):\n    try:\n        text = transcribe_chunk(chunk, \"groq\", timeout=300)\n        break\n    except TranscribeError:\n        if attempt == 2:\n            raise\n        time.sleep(2 ** attempt)","handlingStrategy":"retry","validationCode":"import socket\nfrom urllib.parse import urlparse\n\ndef provider_endpoint_reachable(endpoint: str, timeout: float = 5.0) -> bool:\n    p = urlparse(endpoint)\n    try:\n        socket.create_connection((p.hostname, p.port or 443), timeout=timeout).close()\n        return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"from agent_reach.transcribe import TranscribeError, transcribe_chunk\nimport time\n\ndef transcribe_with_retry(chunk, provider, attempts=3):\n    for i in range(attempts):\n        try:\n            return transcribe_chunk(chunk, provider, timeout=300)\n        except TranscribeError as e:\n            if \"network error\" not in str(e) or i == attempts - 1:\n                raise\n            time.sleep(2 ** i)","preventionTips":["Pass timeout=300 when uploading from slow uplinks","Verify egress/proxy env (HTTPS_PROXY) in containers before batch jobs","Reserve allow_provider_fallback=True (auto mode) as the resilience path"],"tags":["network","timeout","provider","retry","transcription"],"backgroundTag":null,"analyzedSha":"93ae1d18c37b707dec053c7c4f9d91cd8ef8943d","analyzedAt":"2026-08-14T22:54:06.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}