fix: allow first push to a project with uninitialized file system#1820
Conversation
The Studio Web backend returns 404 from FileOperations/Structure for projects whose file system was never initialized (e.g. a freshly created Function project), even though the project exists. This made the first 'uipath push' impossible: the coded-agent validation crashed with an unhandled EnrichedException before any file could be uploaded. Treat a 404 from the Structure endpoint as an empty project structure, and let ensure_coded_agent_project_async accept an empty (never-pushed) remote project so the first push can bootstrap the files. Other HTTP errors still propagate unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4ff596a to
b82f3c4
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes a bootstrap issue in the uipath push CLI flow when targeting a newly created Studio Web Function project whose remote file system is not yet initialized (backend returns 404 for FileOperations/Structure). It updates the Studio Web project validation/structure retrieval so the first push can succeed and initialize the remote tree.
Changes:
- Treat
FileOperations/Structure404 as an empty remote structure inStudioClient.get_project_structure_async. - Allow coded-agent validation to pass when the remote structure is empty (interpreted as “never pushed yet”).
- Add a CLI test covering first push to an uninitialized remote project (Structure 404 → push succeeds).
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
packages/uipath/src/uipath/_cli/_utils/_studio_project.py |
Treats remote Structure 404 as empty structure and relaxes coded-agent validation for empty projects. |
packages/uipath/tests/cli/test_push.py |
Adds regression test ensuring first push succeeds when remote Structure initially returns 404. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try: | ||
| response = await self.uipath.api_client.request_async( | ||
| "GET", | ||
| url=f"{self.file_operations_base_url}/Structure", | ||
| scoped="org", | ||
| ) | ||
| structure = ProjectStructure.model_validate(response.json()) | ||
| except EnrichedException as e: | ||
| # The backend returns 404 for projects whose file system was never | ||
| # initialized (e.g. a freshly created Function project): treat it | ||
| # as an empty structure so the first push can bootstrap the files. | ||
| if e.status_code != 404: | ||
| raise | ||
| structure = ProjectStructure(name="root", folders=[], files=[]) | ||
|
|
andreitava-uip
left a comment
There was a problem hiding this comment.
should be fine. I don't think we have any callers that explicitly handle 404s
|



Problem
uipath pushfails on a freshly created Function project with:or, depending on the backend response, an unhandled
EnrichedExceptiontraceback (404).The Studio Web backend returns 404 from
FileOperations/Structurefor projects whose file system was never initialized — even though the project exists (GET /Project/{id}returns 200 withprojectType: "Function"and an emptyrootFolder). Sincepushis exactly what would upload the first files, this is a bootstrap deadlock: the coded-agent validation (added in #937) blocks the very push that would initialize the project.Verified against a live tenant: the FileOperations write path works fine on such a project; only
Structure404s until the first file exists. After the first push,Structurereturns 200 with the full tree.Fix
StudioClient.get_project_structure_async: treat a 404 fromFileOperations/Structureas an empty project structure (first push bootstraps the files). Other HTTP errors propagate unchanged.ensure_coded_agent_project_async: an empty remote structure (no files, no folders) is a never-pushed project — allow it instead of raisingNonCodedAgentProjectException.Testing
test_first_push_to_uninitialized_project: Structure returns 404 → push succeeds and uploads all files.test_push_non_coded_agent_project(remote with files but nopyproject.tomlstill errors) andtest_push_with_api_error(401 still propagates) keep passing.tests/cli/test_push.py: 33 passed;tests/cli/test_pull.py: 12 passed; ruff + mypy clean.🤖 Generated with Claude Code