can1357/oh-my-pi · error · ValueError

ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY must both b

Error message

ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY must both be set together (or both empty).

What it means

The _validate_proxy_or_pat() model validator requires ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY to be set together: proxy mode without the HMAC key cannot sign requests, and an HMAC key without a URL has nowhere to send them. A mismatch (has_url != has_key) raises ValueError.

Source

Thrown at python/robomp/src/config.py:247

    def _validate_proxy_or_pat(self) -> Settings:
        """Enforce mutual exclusion between PAT and proxy mode.

        - Both set → reject (silent fallback to direct GitHub would defeat
          the isolation goal).
        - Proxy URL set but no HMAC key (or vice versa) → reject (gh-proxy
          would either be unauthenticated or unreachable).
        - Neither set → also reject; SOMETHING needs to talk to GitHub.
        """
        has_token = self.github_token is not None
        has_url = bool(self.gh_proxy_url)
        has_key = self.gh_proxy_hmac_key is not None
        if has_token and has_url:
            raise ValueError(
                "GITHUB_TOKEN and ROBOMP_GH_PROXY_URL are mutually exclusive — "
                "set ONE to choose between direct-PAT and gh-proxy modes."
            )
        if has_url != has_key:
            raise ValueError(
                "ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY must both be set together (or both empty)."
            )
        if not has_token and not has_url:
            raise ValueError(
                "no GitHub access configured: set GITHUB_TOKEN, or set "
                "ROBOMP_GH_PROXY_URL + ROBOMP_GH_PROXY_HMAC_KEY to use gh-proxy."
            )
        return self

    @field_validator("repo_allowlist_raw", mode="before")
    @classmethod
    def _coerce_allowlist(cls, v: object) -> str:
        if v is None:
            return ""
        if isinstance(v, str):
            return v
        if isinstance(v, (list, tuple)):
            return ",".join(str(item) for item in v)

View on GitHub (pinned to 9690622007)

Solutions

  1. Set both ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY together.
  2. If you don't intend to use gh-proxy, remove both variables and configure GITHUB_TOKEN instead.
  3. Check secret injection so the HMAC key is actually mounted/interpolated.
  4. Verify exact env var spelling in .env and deployment manifests.

Example fix

// before
ROBOMP_GH_PROXY_URL=http://gh-proxy:8080
# ROBOMP_GH_PROXY_HMAC_KEY missing
// after
ROBOMP_GH_PROXY_URL=http://gh-proxy:8080
ROBOMP_GH_PROXY_HMAC_KEY=<shared-secret>
Defensive patterns

Strategy: validation

Validate before calling

import os
has_url, has_key = bool(os.environ.get("ROBOMP_GH_PROXY_URL")), bool(os.environ.get("ROBOMP_GH_PROXY_HMAC_KEY"))
if has_url != has_key:
    raise SystemExit("ROBOMP_GH_PROXY_URL and ROBOMP_GH_PROXY_HMAC_KEY must be set together")

Type guard

def proxy_pair_complete(env: dict) -> bool:
    return bool(env.get("ROBOMP_GH_PROXY_URL")) == bool(env.get("ROBOMP_GH_PROXY_HMAC_KEY"))

Try / catch

try:
    cfg = Settings(_env_file=".env")
except ValidationError as exc:
    sys.exit(f"configuration error: {exc}")

Prevention

When it happens

Trigger: Constructing Settings with gh_proxy_url set but gh_proxy_hmac_key missing, or the key set while the URL is empty/absent.

Common situations: Only the URL added to .env (the key was meant to come from a secret store but was not wired); key rotation removed one variable; typo in one of the two names; partial copy-paste of a config snippet.

Related errors


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