can1357/oh-my-pi · error · HTTPException

comments[{idx}].start_side must be RIGHT or LEFT

Error message

comments[{idx}].start_side must be RIGHT or LEFT

What it means

When a review comment spans a range, the optional `start_side` must be a string exactly RIGHT or LEFT. `_require_review_comments` raises this HTTP 400 for the offending index if the provided value differs.

Source

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

    comments: list[dict[str, Any]] = []
    for idx, item in enumerate(value):
        if not isinstance(item, dict):
            raise HTTPException(400, f"comments[{idx}] must be an object")
        path = _require_str(item.get("path"), f"comments[{idx}].path")
        line = _require_int(item.get("line"), f"comments[{idx}].line")
        body = _require_str(item.get("body"), f"comments[{idx}].body")
        side = str(item.get("side") or "RIGHT")
        if side not in ("RIGHT", "LEFT"):
            raise HTTPException(400, f"comments[{idx}].side must be RIGHT or LEFT")
        comment: dict[str, Any] = {"path": path, "line": line, "side": side, "body": body}
        start_line = item.get("start_line")
        if start_line is not None:
            comment["start_line"] = _require_int(start_line, f"comments[{idx}].start_line")
        start_side = item.get("start_side")
        if start_side is not None:
            start_side_str = _require_str(start_side, f"comments[{idx}].start_side")
            if start_side_str not in ("RIGHT", "LEFT"):
                raise HTTPException(400, f"comments[{idx}].start_side must be RIGHT or LEFT")
            comment["start_side"] = start_side_str
        comments.append(comment)
    return comments


def _pool_dir(cfg: Settings, repo: str) -> Path:
    _validate_repo_name(repo)
    return Path(cfg.workspace_root) / "_pool" / repo.replace("/", "__")


def _workspace_repo_dir(cfg: Settings, workspace_key: str) -> Path:
    # Defense-in-depth: workspace_key is constructed by `sandbox.workspace_key`
    # as `<repo_with_underscores>__<number>`. Reject anything outside that shape.
    if "/" in workspace_key or workspace_key.startswith(".") or ".." in workspace_key:
        raise HTTPException(400, f"invalid workspace_key {workspace_key!r}")
    return Path(cfg.workspace_root) / workspace_key / "repo"

View on GitHub (pinned to 9690622007)

Solutions

  1. Send start_side as exactly "RIGHT" or "LEFT" (uppercase string), or omit it for single-line comments.
  2. Only include start_side when start_line is also present — ranged comments need both.
  3. Normalize with raw.strip().upper() client-side and validate against {"RIGHT","LEFT"} before sending.
  4. Remove PENDING values, which GitHub's API accepts but this proxy does not.

Example fix

// before
{"path": "a.py", "line": 10, "start_line": 5, "start_side": "PENDING", "body": "x"}
// after
{"path": "a.py", "line": 10, "start_line": 5, "start_side": "LEFT", "body": "x"}
Defensive patterns

Strategy: validation

Validate before calling

if raw is not None:
    s = str(raw).strip().upper()
    if s not in ("RIGHT", "LEFT"):
        raise ValueError(f"start_side must be RIGHT or LEFT, got {raw!r}")
    comment["start_side"] = s

Type guard

def is_valid_start_side(v: object) -> TypeGuard[str]:
    return isinstance(v, str) and v in ("RIGHT", "LEFT")

Try / catch

try:
    resp = http.post(f"{base}/pr/{n}/review", json=payload)
    resp.raise_for_status()
except httpx.HTTPStatusError as e:
    if e.response.status_code == 400 and "start_side must be" in e.response.text:
        raise ValueError("start_side must be exactly 'RIGHT' or 'LEFT' (no PENDING)") from e
    raise

Prevention

When it happens

Trigger: submit_pr_review with a comment carrying start_side values like "right", "SAME", "PENDING", or a non-string coerced through _require_str.

Common situations: Multi-line review comments copied from GitHub GraphQL payloads where start_side may be PENDING; clients confusing start_side with start_line; lowercase enum values from internal tooling.

Related errors


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