can1357/oh-my-pi · error · HTTPException

unauthenticated

Error message

unauthenticated

What it means

_authenticate validates the caller's GitHub token via the configured auth verifier; when the verification result is not ok, the proxy logs the reason and returns HTTP 401 'unauthenticated'. Every data endpoint (get_repo, list_workflow_runs, get_job_log_tail, etc.) calls this before doing work.

Source

Thrown at python/robomp/src/proxy/server.py:460

    async def _authenticate(request: Request) -> bytes:
        body = await _read_body_capped(request)
        ts = request.headers.get(HEADER_TIMESTAMP)
        sig = request.headers.get(HEADER_SIGNATURE)
        target = _request_target(request)
        result = verify(
            method=request.method,
            path=target,
            body=body,
            timestamp=ts,
            signature=sig,
            key=_resolve_hmac_key(settings),
        )
        if not result.ok:
            log.warning(
                "gh-proxy auth rejected",
                extra={"reason": result.reason, "path": request.url.path},
            )
            raise HTTPException(status.HTTP_401_UNAUTHORIZED, "unauthenticated")
        return body

    # ---- meta ----
    @app.get("/healthz")
    async def healthz() -> dict[str, str]:
        return {"status": "ok"}

    # ---- reads ----
    @app.get("/gh/v1/authenticated_login")
    async def authenticated_login(request: Request) -> dict[str, str]:
        await _authenticate(request)
        github: GitHubClient = request.app.state.github
        try:
            login = await github.get_authenticated_login()
        except GitHubError as exc:
            raise HTTPException(exc.status, exc.message) from exc
        return {"login": login}

View on GitHub (pinned to 9690622007)

Solutions

  1. Set/supply a current, valid GitHub token in the Authorization header the proxy expects
  2. Verify the token works: curl -H "Authorization: Bearer $TOKEN" https://api.github.com/user
  3. Regenerate the PAT if expired or revoked and update the stored secret
  4. Check proxy logs ('gh-proxy auth rejected' reason field) for the specific rejection cause

Example fix

// before
fetch("http://proxy/gh/v1/repo?repo=o/r")
// after
fetch("http://proxy/gh/v1/repo?repo=o/r", {
  headers: { Authorization: `Bearer ${process.env.GH_PROXY_TOKEN}` },
})
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check token shape before calling
if (!process.env.GH_PROXY_TOKEN) throw new Error("GH_PROXY_TOKEN not set");

Try / catch

try {
  const res = await fetch(proxy + "/gh/v1/repo?repo=o/r", { headers: { Authorization: `Bearer ${token}` } });
  if (res.status === 401) {
    // token missing/expired/revoked: prompt re-auth or fail with clear message
    throw new Error("proxy rejected credentials — refresh your GitHub token");
  }
} catch (err) { /* handle */ }

Prevention

When it happens

Trigger: Calling any /gh/v1/* endpoint without a token, with an expired/revoked GitHub PAT, with a token from the wrong scope/issuer, or with a malformed Authorization header the verifier rejects.

Common situations: Expired classic PATs (or fine-grained tokens past their expiration); missing GH_TOKEN in a new environment/CI job; token rotated but the proxy client still uses the old value; connecting to the proxy from a host not on its allowlist.

Understand the failure class

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/9738a9950b0904bc. Report an issue: GitHub.