{"record":{"id":"c647e20553dcb991","repo":"can1357/oh-my-pi","slug":"remote-url-does-not-match-repo-expected-repo-r","errorCode":null,"errorMessage":"remote url does not match repo {expected_repo!r}","messagePattern":"remote url does not match repo (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"python/robomp/src/proxy/server.py","lineNumber":335,"sourceCode":"    if (parsed.scheme or \"\").lower() != \"https\":\n        raise HTTPException(400, f\"remote url must be https://github.com/{expected_repo}[.git]\")\n    if parsed.username or parsed.password:\n        raise HTTPException(400, \"remote url must not contain embedded credentials\")\n    try:\n        port = parsed.port\n    except ValueError as exc:\n        raise HTTPException(400, \"remote url has invalid port\") from exc\n    if port is not None:\n        raise HTTPException(400, \"remote url must not specify a port\")\n    if (parsed.hostname or \"\").lower() != \"github.com\":\n        raise HTTPException(400, f\"remote url host must be github.com for repo {expected_repo!r}\")\n    if parsed.params or parsed.query or parsed.fragment:\n        raise HTTPException(400, \"remote url must not contain params, query, or fragment\")\n    path = parsed.path.strip(\"/\")\n    if path.endswith(\".git\"):\n        path = path[:-4]\n    if path.lower() != expected_repo.lower():\n        raise HTTPException(400, f\"remote url does not match repo {expected_repo!r}\")\n    return _github_url_for_repo(expected_repo)\n\n\ndef _remote_auth_for_url(url: str, expected_repo: str, token: str) -> _RemoteAuth:\n    raw = url.strip()\n    if not raw or raw != url:\n        raise HTTPException(400, \"remote url must not be empty or padded\")\n    if _FORBIDDEN_URL_BYTES_RE.search(raw):\n        raise HTTPException(400, \"remote url contains forbidden control bytes\")\n    if raw.startswith(\"-\"):\n        raise HTTPException(400, \"remote url must not start with '-'\")\n    if _REMOTE_HELPER_RE.match(raw):\n        raise HTTPException(400, \"git remote helper transports are disabled\")\n    scheme = (urlparse(raw).scheme or \"\").lower()\n    if scheme in (\"http\", \"https\"):\n        normalized = _normalized_github_https_url(raw, expected_repo)\n        return _RemoteAuth(url=normalized, token=token, auth_url=normalized)\n    return _RemoteAuth(url=raw, token=None, auth_url=None)","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy/server.py#L317-L353","documentation":"Raised when the origin URL points at github.com but its repository path does not match the expected repo for the request (compared case-insensitively after stripping .git). This is a safety check: the proxy refuses to operate on a worktree whose origin belongs to a different repo than the one the client claims, preventing cross-repo operations.","triggerScenarios":"Proxied git op for expected_repo X where the worktree origin path resolves to Y — e.g. a fork (acme/repo-fork), a typo in owner/name, wrong case handling (path compares lowercased so only actual name mismatches count), or the worktree's origin was re-pointed at a mirror.","commonSituations":"Reusing a worktree cloned from a fork or a different project for a proxy request for another repo; renamed/moved repos where the remote still shows the old slug; misconfigured proxy request payload naming the wrong expected_repo.","solutions":["Verify which repo the worktree actually tracks: `git -C <dir> remote get-url origin`","If the worktree is for the wrong repo, clone/point a worktree of the correct repo: `git remote set-url origin https://github.com/<expected_repo>.git`","If the request's expected_repo is wrong, fix the client/proxy request payload to name the repo the worktree tracks","If the repo was renamed on GitHub, update the remote to the new slug"],"exampleFix":"// before: worktree points at a fork but request targets acme/repo\n$ git remote get-url origin  # https://github.com/acme/repo-fork.git\n// after\n$ git remote set-url origin https://github.com/acme/repo.git","handlingStrategy":"validation","validationCode":"import subprocess\nfrom urllib.parse import urlparse\n\ndef origin_matches_repo(repo_dir: str, expected_repo: str) -> bool:\n    r = subprocess.run([\"git\", \"-C\", repo_dir, \"remote\", \"get-url\", \"origin\"],\n                       capture_output=True, text=True, check=False)\n    if r.returncode != 0:\n        return False\n    path = urlparse(r.stdout.strip()).path.strip(\"/\")\n    if path.endswith(\".git\"):\n        path = path[:-4]\n    return path.lower() == expected_repo.lower()","typeGuard":null,"tryCatchPattern":"from fastapi import HTTPException\n\ntry:\n    result = client.post(\"/git/op\", json={\"repo\": \"acme/repo\"})\nexcept HTTPException as e:\n    if e.status_code == 400 and \"does not match repo\" in e.detail:\n        reassociate_worktree(worktree_dir, \"acme/repo\")  # correct repo or request\n    else:\n        raise","preventionTips":["Keep a 1:1 mapping between worktrees and repos; never reuse a fork's worktree for the upstream repo","Include the repo slug in worktree directory names to prevent mixups","Verify `git remote get-url origin` matches the requested repo before proxy calls","Update remotes after repo renames on GitHub"],"tags":["git","remote-url","proxy","repo-mismatch"],"backgroundTag":"git-remote-repo-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}