can1357/oh-my-pi · error · ValueError

ROBOMP_BOT_LOGIN must be a non-empty GitHub login

Error message

ROBOMP_BOT_LOGIN must be a non-empty GitHub login

What it means

The Settings model normalizes ROBOMP_BOT_LOGIN with a pydantic validator that strips whitespace and a leading @, removes a trailing "[bot]" suffix, and requires a non-empty remainder. An empty value (or one that normalizes to empty, like "@[bot]") raises ValueError during config validation.

Source

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

    natives_cache_gc_interval_seconds: float = Field(3600.0, alias="ROBOMP_NATIVES_CACHE_GC_INTERVAL_SECONDS")

    # Post-run workspace cache reclamation. Every task run reinstalls
    # node_modules (`ensure_workspace_dependencies`), so between runs the
    # checkout's node_modules and the workspace-private bun install cache are
    # dead weight — multiple GB per issue that would otherwise persist until
    # the issue closes and exhaust the disk. When enabled, the worker strips
    # them after every event and WorkerPool.start() sweeps all workspaces once
    # at boot. Costs a dependency re-download on the next run for that issue.
    reclaim_workspace_caches: bool = Field(True, alias="ROBOMP_RECLAIM_WORKSPACE_CACHES")

    @field_validator("bot_login", mode="after")
    @classmethod
    def _require_bot_login(cls, value: str) -> str:
        cleaned = value.strip().removeprefix("@").lower()
        if cleaned.endswith("[bot]"):
            cleaned = cleaned[:-5]
        if not cleaned:
            raise ValueError("ROBOMP_BOT_LOGIN must be a non-empty GitHub login")
        return cleaned

    @field_validator("replay_token", mode="before")
    @classmethod
    def _blank_replay_disables(cls, value: object) -> object:
        # Treat empty/whitespace strings as 'disabled'. Without this, an empty
        # ROBOMP_REPLAY_TOKEN becomes SecretStr("") which the server would
        # happily compare against an empty X-Robomp-Replay-Token header.
        if isinstance(value, str) and not value.strip():
            return None
        if hasattr(value, "get_secret_value"):
            inner = value.get_secret_value()  # type: ignore[attr-defined]
            if isinstance(inner, str) and not inner.strip():
                return None
        return value

    @field_validator("github_token", mode="before")
    @classmethod

View on GitHub (pinned to 9690622007)

Solutions

  1. Set ROBOMP_BOT_LOGIN to an actual GitHub login, e.g. ROBOMP_BOT_LOGIN=my-robot.
  2. You may include @ and [bot] suffix — they are stripped — but the underlying name must be non-empty.
  3. If the bot is optional, remove the variable entirely if the schema allows omission rather than leaving it blank.
  4. Check .env interpolation so an empty CI variable is not silently written.

Example fix

// before (.env)
ROBOMP_BOT_LOGIN=@[bot]
// after
ROBOMP_BOT_LOGIN=@my-robot[bot]
Defensive patterns

Strategy: validation

Validate before calling

login = (os.environ.get("ROBOMP_BOT_LOGIN") or "").strip().removeprefix("@").removesuffix("[bot]")
if not login:
    raise SystemExit("ROBOMP_BOT_LOGIN must name a bot account, e.g. 'my-robot' or '@my-robot[bot]'")

Type guard

def is_valid_bot_login(value: str) -> bool:
    cleaned = value.strip().removeprefix("@").removesuffix("[bot]")
    return bool(cleaned)

Try / catch

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

Prevention

When it happens

Trigger: Setting ROBOMP_BOT_LOGIN to "", whitespace, "@", "[bot]", or "@[bot]" when constructing Settings (e.g. from env at CLI startup).

Common situations: Empty placeholder in .env files (ROBOMP_BOT_LOGIN=); template variable that failed to interpolate; user pasting just the [bot] suffix expecting the validator to infer a name; CI secrets configured as empty strings.

Related errors


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