{"record":{"id":"db835d202cc7746d","repo":"usestrix/strix","slug":"unavailable-db835d","errorCode":"unavailable","errorMessage":"unavailable","messagePattern":"unavailable","errorType":"error_code","errorClass":"RelayError","httpStatus":null,"severity":"error","filePath":"strix/interface/viewer/auth.py","lineNumber":154,"sourceCode":"def _post_json(path: str, payload: dict[str, Any], *, timeout: int) -> tuple[int, dict[str, Any]]:\n    \"\"\"POST JSON to the relay. Returns (status, parsed body).\n\n    Raises RelayError(\"unavailable\") for network/transport failures. HTTP\n    error responses (4xx/5xx) are returned as (status, body) for the caller to\n    map, not raised.\n    \"\"\"\n    url = f\"{_app_url()}{path}\"\n    try:\n        with requests.post(\n            url,\n            json=payload,\n            headers={\"Accept\": \"application/json\"},\n            timeout=timeout,\n        ) as response:\n            return response.status_code, _parse_body(response.content)\n    except requests.RequestException as exc:\n        logger.warning(\"relay request to %s failed: %s\", path, exc)\n        raise RelayError(\"unavailable\") from exc\n\n\ndef _parse_body(raw: bytes) -> dict[str, Any]:\n    try:\n        data = json.loads(raw or b\"{}\")\n    except json.JSONDecodeError:\n        return {}\n    return data if isinstance(data, dict) else {}\n\n\ndef otp_start(email: str) -> None:\n    \"\"\"Ask the relay to email a verification code. Raises RelayError on failure.\"\"\"\n    status, data = _post_json(\"/api/oss/otp/start\", {\"email\": email}, timeout=_OTP_TIMEOUT)\n    if status == 200:\n        return\n    if status == 429:\n        raise RelayError(\"rate_limited\")\n    if status == 400:","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/interface/viewer/auth.py#L136-L172","documentation":"RelayError('unavailable') raised by _post_json() in strix/interface/viewer/auth.py when the HTTP request to the Strix relay (app.strix.ai) raises requests.RequestException — connection refused, DNS failure, TLS error, or timeout. It is the generic network-level failure for all relay endpoints (/api/oss/otp/start, /otp/verify, /feedback, /report/send).","triggerScenarios":"Any otp_start(), otp_verify(), feedback_submit(), or report_send() call while offline, behind a blocking proxy, with DNS resolution failure for the app URL, or when the relay endpoint returns an unmapped status code (the final 'raise RelayError(\"unavailable\")' fallbacks). Also raised by otp_verify when a 200 response lacks a parseable expires_at (gate fails closed).","commonSituations":"Corporate egress proxy or firewall blocking app.strix.ai; airplane mode / flaky WiFi during OTP verification; relay temporarily down or returning 5xx; self-signed TLS interception appliance; typo in a custom app URL override.","solutions":["Check basic connectivity: curl -sS https://app.strix.ai/ -o /dev/null -w '%{http_code}'","Configure proxy env vars if egress requires them: export HTTPS_PROXY=http://proxy.corp:8080","Retry after a short delay — transient network/DNS failures commonly clear","If behind TLS interception, ensure the corporate CA is in the trust store (REQUESTS_CA_BUNDLE=/path/to/ca.pem)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import socket, urllib.request\n\ndef relay_reachable(url=\"https://app.strix.ai\") -> bool:\n    try:\n        urllib.request.urlopen(url, timeout=5)\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"from strix.interface.viewer.auth import RelayError\n\nfor attempt in range(3):\n    try:\n        otp_start(email)\n        break\n    except RelayError as e:\n        if e.code == \"unavailable\" and attempt < 2:\n            time.sleep(2 ** attempt)\n            continue\n        raise","preventionTips":["Verify egress to app.strix.ai before starting verification flows","Set HTTPS_PROXY in proxied environments","Treat 'unavailable' as retryable but cap retries with backoff","Keep the relay URL configuration pristine"],"tags":["strix","network","relay","viewer","auth"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}