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
- Send start_side as exactly "RIGHT" or "LEFT" (uppercase string), or omit it for single-line comments.
- Only include start_side when start_line is also present — ranged comments need both.
- Normalize with raw.strip().upper() client-side and validate against {"RIGHT","LEFT"} before sending.
- 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
- Only set start_side together with start_line for ranged comments
- Map GraphQL PENDING start_side to the appropriate RIGHT/LEFT before posting
- Normalize uppercase/whitespace on enum inputs
- Centralize comment building so enums are validated in one place
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
- comments[{idx}].side must be RIGHT or LEFT
- missing/invalid 'comments'
- comments[{idx}] must be an object
- missing/invalid 'slot_uid'
- invalid '{field}': must be array of strings
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7b80a71a8740c7fd.
Report an issue: GitHub.