Panniantong/Agent-Reach · error · RuntimeError
curl is unavailable for the V2EX TLS fallback
Error message
curl is unavailable for the V2EX TLS fallback
What it means
V2EX channel fetches JSON with urllib first; when Python's TLS stack fails with a known TLS-EOF error, it retries with the OS curl binary (see _get_json_with_curl in agent_reach/channels/v2ex.py:80). This RuntimeError is raised when shutil.which('curl') finds no curl executable, so the TLS fallback path cannot run. It means the environment lacks curl or curl is not on PATH.
Source
Thrown at agent_reach/channels/v2ex.py:90
or "eof occurred in violation of protocol" in text
):
return True
for nested in (
getattr(current, "reason", None),
current.__cause__,
current.__context__,
):
if isinstance(nested, BaseException):
pending.append(nested)
return False
def _get_json_with_curl(url: str) -> Any:
"""Fetch bounded JSON with the OS curl TLS stack."""
_validate_api_url(url)
curl = shutil.which("curl")
if not curl:
raise RuntimeError("curl is unavailable for the V2EX TLS fallback")
command = [
curl,
"--fail",
"--silent",
"--show-error",
"--proto",
"=https",
"--connect-timeout",
"5",
"--max-time",
str(_TIMEOUT),
"--max-filesize",
str(_MAX_RESPONSE_BYTES),
"--header",
f"User-Agent: {_UA}",
"--url",
url,View on GitHub (pinned to 93ae1d18c3)
Solutions
- Install curl on the host (apt-get install curl / apk add curl / brew install curl)
- Verify `which curl` resolves in the same environment agent-reach runs in (print os.environ['PATH'])
- If curl exists but is not found, add its directory to PATH or invoke agent-reach from a shell where PATH includes /usr/bin
- As a library workaround, call V2EX URLs directly with your own HTTP client when this error surfaces
Example fix
# before: slim Dockerfile with no curl FROM python:3.12-slim RUN pip install agent-reach # after: install curl so the V2EX TLS fallback works FROM python:3.12-slim RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* RUN pip install agent-reach
Defensive patterns
Strategy: validation
Validate before calling
import shutil
def v2ex_fallback_available() -> bool:
"""True when the curl TLS fallback can run on this host."""
return shutil.which("curl") is not None
# before calling V2EXChannel
if not v2ex_fallback_available():
raise SystemExit("install curl, or route V2EX reads through your own HTTP client") Prevention
- Base your agent-reach container image on one that ships curl, or add an explicit curl install step
- Smoke-test deployments with `shutil.which('curl')` before enabling V2EX-dependent features
- Treat this RuntimeError as an environment defect: fix the host rather than catching and ignoring
When it happens
Trigger: Any V2EXChannel.read()/search() call where urllib first raises an unexpected-TLS-EOF error and _get_json escalates to _get_json_with_curl, on a host where `curl` is not installed or PATH is stripped (minimal containers, alpine without curl, systemd services with limited PATH).
Common situations: Running agent-reach inside slim Docker images (python:3.x-slim has no curl), restricted CI runners, NixOS/Homebrew environments where curl is not linked into the shell PATH, or subprocess environments where PATH is sanitized.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- curl could not complete the V2EX TLS fallback
- invalid V2EX API URL
- only the V2EX HTTPS API is allowed
- V2EX API response exceeds the 1 MiB safety limit
- {binary} not found in PATH
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/7cd7c77fd65fb668.
Report an issue: GitHub.