{"record":{"id":"c6f73a5eea2409ee","repo":"can1357/oh-my-pi","slug":"workspace-not-found-workspace-key","errorCode":null,"errorMessage":"workspace not found: {workspace_key}","messagePattern":"workspace not found: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"python/robomp/src/proxy/server.py","lineNumber":920,"sourceCode":"        except GitCommandError as exc:\n            return _git_error_response(exc)\n        return JSONResponse({\"pool_dir\": str(target)})\n\n    @app.post(\"/gh/v1/git/push\")\n    async def git_push_endpoint(request: Request) -> JSONResponse:\n        data = await _json_body(request)\n        repo = _require_str(data.get(\"repo\"), \"repo\")\n        workspace_key = _require_str(data.get(\"workspace_key\"), \"workspace_key\")\n        branch = _require_branch(data.get(\"branch\"))\n        expected_head = _require_str(data.get(\"expected_head\"), \"expected_head\")\n        slot_uid = _optional_slot_uid(data.get(\"slot_uid\"))\n        # Sanity-check workspace_key matches the repo claim.\n        expected_prefix = repo.replace(\"/\", \"__\") + \"__\"\n        if not workspace_key.startswith(expected_prefix):\n            raise HTTPException(400, \"workspace_key does not match repo\")\n        repo_dir = _workspace_repo_dir(settings, workspace_key)\n        if not repo_dir.is_dir():\n            raise HTTPException(404, f\"workspace not found: {workspace_key}\")\n        remote = await asyncio.to_thread(\n            _origin_remote_auth,\n            repo_dir,\n            repo,\n            _resolve_token(settings),\n            push=True,\n            slot_uid=slot_uid,\n        )\n        try:\n            result = await _run_git_op(\n                git_push,\n                repo_dir,\n                branch=branch,\n                expected_head=expected_head,\n                token=remote.token,\n                remote_url=remote.url,\n                auth_url=remote.auth_url,\n                slot_uid=slot_uid,","sourceCodeStart":902,"sourceCodeEnd":938,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy/server.py#L902-L938","documentation":"After validating the workspace_key prefix, `git_push_endpoint` resolves the workspace directory via `_workspace_repo_dir` and requires it to exist. If no directory exists for that workspace_key on the proxy host, it returns HTTP 404. The proxy has no cloned workspace under that key to push from.","triggerScenarios":"POSTing to /gh/v1/git/push with a workspace_key that was never cloned on this proxy instance, was garbage-collected/cleaned up, or exists on a different proxy deployment than the one being called.","commonSituations":"Proxy restarted with ephemeral storage wiping workspaces, calling a different proxy replica than the one holding the workspace, stale workspace_key cached by the client after cleanup, or typo in the key suffix.","solutions":["Re-clone the repo through the proxy (git/clone) to recreate the workspace before pushing","Verify you are calling the same proxy instance/deployment that owns the workspace","Check proxy workspace storage configuration/persistence across restarts","Confirm the workspace_key string is correct (no truncation or stale cache)"],"exampleFix":"// before: push against a vanished workspace\nawait push({ workspace_key: \"owner__repo__old-task\" })\n// after: recreate the workspace first\nawait clone({ repo: \"owner/repo\", clone_url, workspace_key: \"owner__repo__new-task\" })\nawait push({ repo: \"owner/repo\", workspace_key: \"owner__repo__new-task\", ... })","handlingStrategy":"try-catch","validationCode":"# probe whether the workspace exists before pushing\nprobe = proxy.git_fetch(repo=repo, workspace_key=key)  # or track workspace lifecycle client-side\n# if you have filesystem/API access: verify the workspace dir exists for this proxy instance","typeGuard":null,"tryCatchPattern":"try:\n    proxy.git_push(repo=repo, workspace_key=key, ...)\nexcept HTTPError as e:\n    if e.response.status_code == 404 and \"workspace not found\" in e.response.text:\n        proxy.git_clone(repo=repo, clone_url=clone_url, workspace_key=key)  # recreate\n        proxy.git_push(repo=repo, workspace_key=key, ...)  # retry once\n    else:\n        raise","preventionTips":["Clone via the proxy immediately before pushing in long pipelines","Use persistent workspace storage across proxy restarts","Pin jobs to the proxy instance that owns the workspace (sticky routing)","Track workspace lifecycle client-side and recreate on demand"],"tags":["http-404","workspace","state","missing-resource"],"backgroundTag":"workspace-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}