can1357/oh-my-pi · error · HTTPException
origin must have exactly one {kind} url
Error message
origin must have exactly one {kind} url What it means
Raised when `git remote get-url origin` returns zero or multiple URLs for origin instead of exactly one. git can return several lines when a remote has multiple URLs configured (url multi-valued via `remote.origin.url` or multiple pushurl entries). The proxy requires an unambiguous single fetch/push URL to authenticate against GitHub.
Source
Thrown at python/robomp/src/proxy/server.py:310
raise HTTPException(504, "timeout reading origin url") from exc
if proc.returncode != 0:
# `git remote get-url` writes nothing useful to stdout on failure; do
# NOT echo stderr to the client (may leak local paths). The proxy log
# already captured the failure.
log.warning("gh-proxy: failed to read origin url", extra={"repo_dir": str(repo_dir)})
raise HTTPException(400, "could not read origin url for worktree")
return [line.strip() for line in proc.stdout.splitlines() if line.strip()]
def _read_single_remote_url(repo_dir: Path, expected_repo: str, *, push: bool, slot_uid: int | None = None) -> str:
urls = list(dict.fromkeys(_read_remote_urls(repo_dir, slot_uid=slot_uid, push=push)))
if len(urls) != 1:
kind = "push" if push else "fetch"
log.warning(
"gh-proxy: refusing git op — origin has ambiguous remote urls",
extra={"expected_repo": expected_repo, "kind": kind, "count": len(urls)},
)
raise HTTPException(400, f"origin must have exactly one {kind} url")
return urls[0]
def _normalized_github_https_url(url: str, expected_repo: str) -> str:
_validate_repo_name(expected_repo)
parsed = urlparse(url)
if (parsed.scheme or "").lower() != "https":
raise HTTPException(400, f"remote url must be https://github.com/{expected_repo}[.git]")
if parsed.username or parsed.password:
raise HTTPException(400, "remote url must not contain embedded credentials")
try:
port = parsed.port
except ValueError as exc:
raise HTTPException(400, "remote url has invalid port") from exc
if port is not None:
raise HTTPException(400, "remote url must not specify a port")
if (parsed.hostname or "").lower() != "github.com":
raise HTTPException(400, f"remote url host must be github.com for repo {expected_repo!r}")View on GitHub (pinned to 9690622007)
Solutions
- Inspect `git config --get-all remote.origin.url` and `git config --get-all remote.origin.pushurl` in the worktree
- Collapse to a single URL: `git remote set-url origin <url>` and remove extra pushurls with `git config --unset-all remote.origin.pushurl` (or `git remote set-url --delete --push origin <extra>`)
- If you need push/fan-out remotes, configure them on a different remote name, not origin
- Re-add the remote cleanly: `git remote remove origin && git remote add origin <url>`
Example fix
// before: multiple push urls on origin $ git remote set-url --add --push origin https://github.com/acme/mirror.git // after: single url, move extra pushes elsewhere $ git remote set-url --delete --push origin https://github.com/acme/mirror.git $ git remote add mirror https://github.com/acme/mirror.git
Defensive patterns
Strategy: validation
Validate before calling
import subprocess
def origin_has_single_url(repo_dir: str) -> bool:
urls = subprocess.run(["git", "-C", repo_dir, "config", "--get-all", "remote.origin.url"],
capture_output=True, text=True, check=False).stdout.split()
return len(urls) == 1 Try / catch
from fastapi import HTTPException
try:
result = client.post("/git/op", json={"repo": "acme/repo"})
except HTTPException as e:
if e.status_code == 400 and "exactly one" in e.detail:
normalize_origin_remote(worktree_dir) # collapse multi-url origin
else:
raise Prevention
- Never use `git remote set-url --add --push` on origin in proxy-managed worktrees; use a separate remote
- Audit worktrees with `git config --get-all remote.origin.url` during setup
- Keep fan-out/mirror push configs on dedicated remotes
When it happens
Trigger: A git operation via the proxy where _read_single_remote_url finds the deduplicated URL list length != 1 for the requested kind (fetch or push): origin configured with multiple pushURLs, or a broken empty remote with no url.
Common situations: `git remote set-url --add --push origin <url>` used for split push/pull setups (e.g. push to a mirror); multi-remote relay configs copied into origin; a remote whose url entry was removed leaving zero urls.
Related errors
- could not read origin url for worktree
- origin remote is unavailable for this repository.
- pr://${parsed.number} could not resolve a default repo from
- Codex Security cloud import requires a verifiable repository
- Isolated task execution requires a Git checkout, but this wo
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/cb3bbcfb086a20f9.
Report an issue: GitHub.