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

  1. Pass exactly one: use pr_head only for fresh PR-review workspaces, existing_branch only when resuming prior work.
  2. Add explicit branching in the caller: `kwargs['pr_head' if pr else 'existing_branch'] = value`.
  3. If both values genuinely exist, decide precedence (resume wins) and drop the other before calling.
  4. 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

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


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