zylon-ai/private-gpt · warning · RuntimeError
openapi_spec_url not found in {ANTHROPIC_STATS_URL}
Error message
openapi_spec_url not found in {ANTHROPIC_STATS_URL} What it means
Raised by fetch_openapi_spec_url in scripts/update_claude_specs.py after downloading the anthropic-sdk-python stats file (ANTHROPIC_STATS_URL) and scanning every line for one starting with 'openapi_spec_url:'. The stats file is expected to advertise the URL of the OpenAPI spec used to generate the SDK's typed client; if no such line exists (format change, redirect serving different content, or an error page), the maintenance script cannot proceed.
Source
Thrown at scripts/update_claude_specs.py:26
import urllib.request
from pathlib import Path
ROOT = Path(__file__).parent.parent
ANTHROPIC_STATS_URL = "https://raw.githubusercontent.com/anthropics/anthropic-sdk-typescript/main/.stats.yml"
ANTHROPIC_PYPI_URL = "https://pypi.org/pypi/anthropic/json"
OPENAPI_TEST_FILE = ROOT / "tests/models/anthropic/test_openapi_schema.py"
PYPROJECT_FILE = ROOT / "pyproject.toml"
def fetch_openapi_spec_url() -> str:
with urllib.request.urlopen(ANTHROPIC_STATS_URL, timeout=15) as resp:
for line in resp.read().decode().splitlines():
if line.startswith("openapi_spec_url:"):
spec_url: str = line.split(":", 1)[1].strip()
return spec_url
raise RuntimeError(f"openapi_spec_url not found in {ANTHROPIC_STATS_URL}")
def fetch_latest_anthropic_version() -> str:
with urllib.request.urlopen(ANTHROPIC_PYPI_URL, timeout=15) as resp:
version: str = json.loads(resp.read().decode())["info"]["version"]
return version
def current_openapi_spec_url() -> str:
source = OPENAPI_TEST_FILE.read_text(encoding="utf-8")
match = re.search(r'^OPENAPI_SPEC_URL\s*=\s*"([^"]*)"', source, re.MULTILINE)
spec_url: str = match.group(1) if match else "<not found>"
return spec_url
def current_anthropic_version() -> str:
source = PYPROJECT_FILE.read_text(encoding="utf-8")
match = re.search(r'"anthropic>=([\d.]+)"', source)View on GitHub (pinned to 4a030776a3)
Solutions
- Fetch the URL manually (curl -sL <ANTHROPIC_STATS_URL> | grep openapi_spec_url) to see what the file currently contains
- If upstream renamed the key, update the prefix check in fetch_openapi_spec_url to the new field name and pin the script to a known-good ref
- Handle redirects/auth: use urlopen with the final URL, or add a retry with backoff for transient failures
- If the metadata line truly moved, locate the current spec URL in the repo and adjust ANTHROPIC_STATS_URL / the parsing accordingly
Example fix
# before
for line in resp.read().decode().splitlines():
if line.startswith("openapi_spec_url:"):
...
# after (diagnose + tolerate format drift)
body = urllib.request.urlopen(ANTHROPIC_STATS_URL, timeout=15).read().decode()
match = re.search(r'^\s*openapi_spec_url\s*:\s*(\S+)', body, re.M)
if not match:
raise RuntimeError(f"openapi_spec_url not found; body preview: {body[:200]!r}")
spec_url = match.group(1) Defensive patterns
Strategy: fallback
Validate before calling
import urllib.request
def stats_url_contains_spec_key(url: str) -> bool:
try:
with urllib.request.urlopen(url, timeout=15) as resp:
return any(
line.startswith("openapi_spec_url:")
for line in resp.read().decode().splitlines()
)
except OSError:
return False
# if False, pin a known-good ref or update the parser before running the script Type guard
null
Try / catch
try:
spec_url = fetch_openapi_spec_url()
except (RuntimeError, OSError) as e:
# fall back to the last known-good URL instead of failing the whole update
spec_url = current_openapi_spec_url()
logger.warning("using cached spec URL %s after fetch failure: %s", spec_url, e) Prevention
- Fetch the stats file and grep it manually before running the refresh job after upstream releases
- Pin the script to a known-good upstream commit/ref rather than a moving branch
- Cache the last-good spec URL in the repo (as tests already do) and fall back to it on fetch/format failures
- Alert on HTML/error bodies (content-type check) so proxy blocks are distinguishable from format drift
When it happens
Trigger: Anthropic changing the stats-file format (renaming the key or switching to YAML/JSON); the URL serving a redirect page or HTML error (proxy block, rate limit) whose body has no matching line; network middleboxes rewriting the response; the script running after upstream removed the metadata line.
Common situations: Scheduled spec-refresh jobs breaking when upstream repo layout changes; corporate proxies returning an HTML block page for raw.githubusercontent URLs; transient GitHub issues serving error bodies with HTTP 200; long-lived forks where the pinned stats URL went stale.
Related errors
- Empty response from generator.
- Could not load tokenizer from '{model_id}': {e}
- Remote tokenizer response did not contain a valid 'tokens' f
- Remote detokenize response did not contain a supported text
- Model server is not available or request failed.
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/19cc45796c480b16.
Report an issue: GitHub.