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

  1. Fetch the URL manually (curl -sL <ANTHROPIC_STATS_URL> | grep openapi_spec_url) to see what the file currently contains
  2. 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
  3. Handle redirects/auth: use urlopen with the final URL, or add a retry with backoff for transient failures
  4. 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

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


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/19cc45796c480b16. Report an issue: GitHub.