can1357/oh-my-pi · error · ValueError
ensure_workspace accepts either pr_head or existing_branch,
Error message
ensure_workspace accepts either pr_head or existing_branch, not both
What it means
ensure_workspace() creates one workspace per issue and accepts exactly one branch source: pr_head (detached checkout of a fetched PR head) or existing_branch (resume an existing branch). Passing both is a caller contract violation — the two modes are mutually exclusive — so it raises ValueError up front before touching the clone pool.
Source
Thrown at python/robomp/src/sandbox.py:895
def ensure_workspace(
self,
*,
repo: str,
number: int,
title: str,
clone_url: str,
default_branch: str,
existing_branch: str | None = None,
pr_head: int | None = None,
author_name: str,
author_email: str,
slot_uid: int | None = None,
) -> Workspace:
"""Create or resume a per-issue worktree."""
with self._repo_lock(repo):
if pr_head is not None and existing_branch is not None:
raise ValueError("ensure_workspace accepts either pr_head or existing_branch, not both")
pool = self.ensure_clone(repo=repo, clone_url=clone_url, default_branch=default_branch)
ws_root = self.workspace_root(repo, number)
repo_dir = ws_root / "repo"
session_dir = ws_root / ".omp-session"
context_dir = ws_root / "context"
artifacts_dir = ws_root / "artifacts"
for path in (ws_root, session_dir, context_dir, context_dir / "repro", artifacts_dir):
path.mkdir(parents=True, exist_ok=True)
branch = (
f"review/pr-{pr_head}"
if pr_head is not None
else existing_branch
or make_branch(
issue_number=number,
title=title,
seed=f"{repo}#{number}",
)View on GitHub (pinned to 9690622007)
Solutions
- Pass exactly one: use pr_head only for fresh PR-review workspaces, existing_branch only when resuming prior work.
- Add explicit branching in the caller: `kwargs['pr_head' if pr else 'existing_branch'] = value`.
- If both values genuinely exist, decide precedence (resume wins) and drop the other before calling.
- Re-run/replay the event after fixing the dispatcher so the failed event is retried with valid kwargs.
Example fix
// before
manager.ensure_workspace(repo=repo, number=n, clone_url=url, default_branch=main,
author_name=a, author_email=e, pr_head=pr_head, existing_branch=branch)
// after
kwargs = {}
if pr_head is not None:
kwargs["pr_head"] = pr_head
elif branch is not None:
kwargs["existing_branch"] = branch
manager.ensure_workspace(repo=repo, number=n, clone_url=url, default_branch=main,
author_name=a, author_email=e, **kwargs) Defensive patterns
Strategy: validation
Validate before calling
if pr_head is not None and existing_branch is not None:
raise ValueError("caller bug: pr_head and existing_branch are mutually exclusive")
ws = manager.ensure_workspace(..., **({"pr_head": pr_head} if pr_head else {"existing_branch": existing_branch})) Try / catch
try:
ws = manager.ensure_workspace(...)
except ValueError as e:
if "not both" in str(e):
log.error("dispatcher bug: both pr_head and existing_branch set", exc_info=True)
raise Prevention
- Build ensure_workspace kwargs conditionally — exactly one branch source.
- Add a unit test covering both the pr_head and existing_branch call shapes.
- Keep new-task and resume-task code paths separate instead of merging optional kwargs.
When it happens
Trigger: Calling SandboxManager.ensure_workspace(repo, number, ..., pr_head=X, existing_branch=Y) with both keyword arguments set to non-None values, e.g. a dispatcher bug that always passes the PR head while a resume path also supplies the stored branch.
Common situations: Handler code that merges 'new PR task' and 'resume existing task' inputs without branching on which is present; refactoring tasks.py so an optional pr_head default stopped being None on the resume path; unit tests constructing kwargs dicts with both keys.
Related errors
- Gemini Files API delete requires a valid file name
- maxAgents must be a positive integer
- Unsupported vault:// file op: ${rawOp}
- Unsupported vault:// vault op: ${rawOp}
- vault:// path resolution only supports plain filesystem path
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c408cad8be47826f.
Report an issue: GitHub.