{"record":{"id":"3291d9131ccd3e85","repo":"can1357/oh-my-pi","slug":"gh-proxy-robomp-gh-proxy-hmac-key-not-configured","errorCode":null,"errorMessage":"gh-proxy: ROBOMP_GH_PROXY_HMAC_KEY not configured","messagePattern":"gh-proxy: ROBOMP_GH_PROXY_HMAC_KEY not configured","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"critical","filePath":"python/robomp/src/proxy/server.py","lineNumber":231,"sourceCode":"\ndef _workspace_repo_dir(cfg: Settings, workspace_key: str) -> Path:\n    # Defense-in-depth: workspace_key is constructed by `sandbox.workspace_key`\n    # as `<repo_with_underscores>__<number>`. Reject anything outside that shape.\n    if \"/\" in workspace_key or workspace_key.startswith(\".\") or \"..\" in workspace_key:\n        raise HTTPException(400, f\"invalid workspace_key {workspace_key!r}\")\n    return Path(cfg.workspace_root) / workspace_key / \"repo\"\n\n\ndef _resolve_token(cfg: Settings) -> str:\n    if cfg.github_token is None:\n        # Will already have been caught at startup, but stay defensive.\n        raise HTTPException(500, \"gh-proxy: GITHUB_TOKEN not configured\")\n    return cfg.github_token.get_secret_value()\n\n\ndef _resolve_hmac_key(cfg: Settings) -> bytes:\n    if cfg.gh_proxy_hmac_key is None:\n        raise HTTPException(500, \"gh-proxy: ROBOMP_GH_PROXY_HMAC_KEY not configured\")\n    return cfg.gh_proxy_hmac_key.get_secret_value().encode(\"utf-8\")\n\n\n_ORIGIN_READ_TIMEOUT_SECONDS = 5.0\n\n\n_REMOTE_HELPER_RE = re.compile(r\"^[A-Za-z][A-Za-z0-9+.-]*::\")\n_FORBIDDEN_URL_BYTES_RE = re.compile(r\"[\\x00-\\x1f\\x7f]|%(?:00|0a|0d)\", re.IGNORECASE)\n_GITHUB_REPO_RE = re.compile(r\"^[A-Za-z0-9][A-Za-z0-9-]{0,38}/[A-Za-z0-9._-]+$\")\n_GIT_PROBE_SCRUBBED_ENV_KEYS = (\n    \"ROBOMP_GIT_HTTP_AUTH\",\n    \"GITHUB_TOKEN\",\n    \"GH_TOKEN\",\n    \"GITHUB_WEBHOOK_SECRET\",\n    \"ROBOMP_REPLAY_TOKEN\",\n    \"ROBOMP_GH_PROXY_HMAC_KEY\",\n)\n","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy/server.py#L213-L249","documentation":"HMAC request authentication needs the shared secret from ROBOMP_GH_PROXY_HMAC_KEY. `_resolve_hmac_key`, invoked by `_authenticate` on every authenticated request, raises this HTTP 500 when the setting is absent, so no request can be verified.","triggerScenarios":"Any proxied request reaching _authenticate while the proxy process was started without ROBOMP_GH_PROXY_HMAC_KEY configured.","commonSituations":"Clients and server deployed from the same template but the server manifest omits the HMAC secret; local dev runs without the .env; secret rotated on clients but not added to the server; typo in the env var name so the loader sees None.","solutions":["Set ROBOMP_GH_PROXY_HMAC_KEY (the shared HMAC secret) in the proxy's environment and restart.","Verify the exact env var spelling — a typo makes the settings field None and triggers this error.","Ensure client and server use the same secret value so HMAC signatures verify after startup succeeds.","In deployments, wire the secret via your secrets manager and confirm the container actually receives it (e.g. docker inspect / kubectl describe)."],"exampleFix":"// before\nservices:\n  gh-proxy:\n    environment: [GITHUB_TOKEN]\n// after\nservices:\n  gh-proxy:\n    environment: [GITHUB_TOKEN, ROBOMP_GH_PROXY_HMAC_KEY]","handlingStrategy":"fallback","validationCode":"import os\nkey = os.environ.get(\"ROBOMP_GH_PROXY_HMAC_KEY\")\nif not key:\n    raise RuntimeError(\"ROBOMP_GH_PROXY_HMAC_KEY must be set on the gh-proxy server\")","typeGuard":"def has_hmac_key(cfg: object) -> TypeGuard[object]:\n    return getattr(cfg, \"gh_proxy_hmac_key\", None) is not None","tryCatchPattern":"try:\n    resp = http.post(f\"{base}/git/fetch\", json=payload, headers=sign(payload))\n    resp.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 500 and \"HMAC_KEY not configured\" in e.response.text:\n        raise RuntimeError(\"gh-proxy missing ROBOMP_GH_PROXY_HMAC_KEY; configure and restart\") from e\n    raise","preventionTips":["Verify env var spelling — a typo makes the settings field None","Provision the HMAC secret via the same secrets pipeline as GITHUB_TOKEN","Keep server and client secrets in sync; rotate both together","Add a health/startup assertion so misconfiguration surfaces before traffic"],"tags":["http-500","configuration","hmac","authentication"],"backgroundTag":"missing-env-var","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}