JuliusBrussee/caveman · error · MiddlewareError

invalid_endpoint

invalid_endpoint

Error message

invalid_endpoint

What it means

The middleware runtime constructor validates the endpoint URL strictly: scheme must be http/https, hostname present, no credentials/query/fragment, and path must be empty or "/". Any other URL shape raises MiddlewareError("invalid_endpoint") at construction time, before any network I/O.

Solutions

  1. Pass a bare origin: scheme + host + optional port only, e.g. "http://127.0.0.1:8080" or "https://proxy.example.com"
  2. Move any path/query into request configuration elsewhere — the runtime only accepts "" or "/" as path
  3. Remove userinfo (user:pass@) from the URL; supply credentials via headers/tokens instead
  4. Pre-validate with urllib.parse.urlsplit before constructing

Example fix

// before
Runtime(endpoint="http://localhost:8080/api/v1?key=abc")
// after
Runtime(endpoint="http://localhost:8080")  # bare origin; no path, query, or credentials
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlsplit
def valid_endpoint(endpoint: str) -> bool:
    u = urlsplit(endpoint)
    return (u.scheme in ('http', 'https') and bool(u.hostname)
            and not u.username and not u.password
            and not u.query and not u.fragment
            and u.path in ('', '/'))

Type guard

def is_bare_origin(endpoint: object) -> bool:
    if not isinstance(endpoint, str):
        return False
    from urllib.parse import urlsplit
    u = urlsplit(endpoint)
    return (u.scheme in ('http', 'https') and bool(u.hostname)
            and not (u.username or u.password or u.query or u.fragment)
            and u.path in ('', '/'))

Try / catch

try:
    runtime = Runtime(endpoint=ep)
except MiddlewareError as e:
    if str(e) == 'invalid_endpoint':
        raise ConfigError(f'endpoint must be a bare http(s) origin, got {ep!r}') from e
    raise

Prevention

When it happens

Trigger: Passing endpoints like "caveman://...", "http://host/base/path", "https://user:pass@host", URLs with ?query or #fragment, or an empty/unparsable endpoint string.

Common situations: Appending a base path (e.g. "http://localhost:8080/api/v1") because other HTTP clients allow it; leaving a template placeholder unfilled; including credentials in the URL out of habit.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/17009efa0e3d655c. Report an issue: GitHub.

Appendix: source

Thrown at packages/sdk/python/caveman_cloud/middleware/runtime.py:67

    return PreflightReport(1, "disabled" if reason == "disabled" else "ready" if reason in ("ready", "record_only") else "unavailable",
                           reason, mode, caps.get("mode"), caps.get("runtime_build") if validate.token(caps.get("runtime_build")) else None,
                           caps.get("policy_revision"), caps.get("persistent"), caps.get("recovery"), PREFLIGHT_ACTIONS[reason])


def _json(value: Any) -> str:
    return json.dumps(value, ensure_ascii=False, separators=(",", ":"), allow_nan=False)


class MiddlewareRuntime:
    def __init__(self, *, endpoint: str = "http://127.0.0.1:8787", token: str | None = None,
                 allow_remote_content: bool = False, mode: str = "compress", deadline_ms: int = 100,
                 retrieve_deadline_ms: int = 5000,
                 strict: bool = False, on_diagnostic: Callable[[dict], None] | None = None,
                 on_report: Callable[[CallReport], None] | None = None):
        url = urlsplit(endpoint)
        local = url.hostname in ("127.0.0.1", "::1", "localhost")
        if url.scheme not in ("http", "https") or not url.hostname or url.username or url.password or url.query or url.fragment or url.path not in ("", "/"):
            raise MiddlewareError("invalid_endpoint")
        if not local and (not allow_remote_content or url.scheme != "https"):
            raise MiddlewareError("remote_content_not_enabled")
        if type(deadline_ms) is not int or deadline_ms <= 0 or mode not in ("off", "record", "compress"):
            raise MiddlewareError("invalid_configuration")
        # A model asking to see an original is waiting on a page of stored text,
        # not on the optimizer in front of a provider call. Separate budget.
        if type(retrieve_deadline_ms) is not int or retrieve_deadline_ms <= 0:
            raise MiddlewareError("invalid_configuration")
        self.endpoint = f"{url.scheme}://{url.netloc}"
        self.mode, self.deadline_ms, self.strict = mode, deadline_ms, strict
        self.retrieve_deadline_ms = retrieve_deadline_ms
        self._token, self._diagnostic = token, on_diagnostic
        self._report_sink, self._last_report = on_report, None
        self._url = url
        self._connections: set[http.client.HTTPConnection] = set()
        self._caps: dict | None = None
        self._bindings: weakref.WeakKeyDictionary[RecoveryBinding, tuple] = weakref.WeakKeyDictionary()
        self._lock = threading.RLock()

View on GitHub (pinned to 3ee70a1026)