Skip to content

fix(desktop): prefer cloud-confirmed v2 project in v1→v2 workspace adopt#4137

Merged
saddlepaddle merged 2 commits into
mainfrom
debug-migration-db-gap
May 6, 2026
Merged

fix(desktop): prefer cloud-confirmed v2 project in v1→v2 workspace adopt#4137
saddlepaddle merged 2 commits into
mainfrom
debug-migration-db-gap

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented May 6, 2026

Summary

  • v1→v2 workspace adopt fails with "Failed to create workspace: Project not found in this organization" when host.db has two projects rows sharing the same repo_path. ImportWorkspacesPage builds its repoPath → v2 id map with last-write-wins Map.set, so an orphan local row (e.g. left over from a manual repair where the cloud counterpart got hard-deleted) can shadow the canonical id. Adopt then forwards the orphan to v2Workspace.create, which can't find it under the user's org.
  • Prefer ids that already appear as a projectId on workspace.cloudList — that's a cheap proxy for "actually exists in cloud" since v2_workspaces FK to v2_projects. Falls back to first-seen when no candidate has cloud workspaces, so the common single-row case is unchanged.
  • Repro on my machine: host.db had 1c99c8eb… (canonical, 26 cloud workspaces) and 07682010… (orphan, no cloud row) both pointing at /Users/satyapatel/code/superset. Pre-fix: every Adopt button errored with the org-scope message. Post-fix: importer resolves to 1c99c8eb… and Adopt succeeds.

Test plan

  • On a host with a duplicate projects row (one cloud-backed, one orphan) sharing a repo_path, open the V1 import modal → "Bring over your workspaces" → Adopt completes for every row.
  • Single-row case still works (regression check on a clean host with one v2 project per repo path).
  • No-candidate case (every host project orphan / no cloud workspaces yet) still falls back to the existing first-seen behavior.

Summary by cubic

Fixes v1→v2 workspace adopt failures by preferring the cloud-backed v2 project when multiple host projects rows share the same repo path. Prevents "Project not found in this organization" errors during Adopt.

  • Bug Fixes
    • When multiple v2 project ids exist for a repoPath, choose the id that appears as a projectId in the cloud workspace list; otherwise keep the first seen.
    • Gate the modal’s Adopt actions on cloudWorkspacesQuery loading and include cloudWorkspacesQuery.data in the memo deps so the mapping updates once cloud data arrives.
    • Single-row and no-cloud cases keep the previous behavior.

Written for commit 24adbb5. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Improved workspace import functionality to better handle duplicate repository paths by prioritizing identifiers that already exist in cloud workspaces.
    • Enhanced the import loading state mechanism to more accurately reflect cloud workspace data availability, providing more reliable progress indication during the import process.

When multiple host.db rows share a repo_path, the importer's repoPath→v2id
map was last-write-wins, so an orphan local project (e.g. left over from a
manual repair) could shadow the canonical id. Workspace adopt then called
v2Workspace.create with the orphan id and tripped the org-scope check with
"Project not found in this organization". Prefer ids that appear as a
projectId on the org's cloud workspace list, falling back to first-seen.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR fixes a "Project not found in this organization" error during v1→v2 workspace adopt that occurred when host.db contained two projects rows sharing the same repo_path — an orphan local row could shadow the cloud-backed canonical ID in the repoPath → v2Id map.

  • The fix builds a Set of project IDs that appear as a projectId on cloudWorkspacesQuery results, then prefers those cloud-confirmed IDs over orphan rows when two projects share a repo_path, while falling back to first-seen for the common single-row case.
  • cloudWorkspacesQuery.isPending is not included in the isLoading gate, so if the cloud workspace query is still in-flight when hostProjectListQuery resolves, the loading spinner drops and projectIdsInCloud is momentarily empty — the orphan ID can win and an eager Adopt click would still fail.

Confidence Score: 4/5

The fix is correct for the described duplicate-row scenario, but the cloud query being excluded from the loading gate means a user with slow network could still trigger the exact error being fixed.

The deduplication logic is sound and handles the orphan-vs-canonical case correctly once all data is available. The one gap is that cloudWorkspacesQuery.isPending isn't included in isLoading, so on slow connections the UI can become interactive before projectIdsInCloud is populated, allowing the orphan project ID to be used for an Adopt call.

apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx — specifically the isLoading derivation and its relationship to the new cloud-query dependency.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx Adds cloud-workspace-backed project ID preference when deduplicating duplicate repo_path rows; cloudWorkspacesQuery.isPending is still excluded from the isLoading gate.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[hostProjectListQuery.data] --> B{Iterate v2 projects}
    C[cloudWorkspacesQuery.data] --> D[Build projectIdsInCloud Set]
    D --> B
    B --> E{existing entry for repoPath?}
    E -- No --> F[Set first-seen id]
    E -- Yes --> G{new id in cloud AND existing NOT in cloud?}
    G -- Yes --> H[Replace with cloud-backed id]
    G -- No --> I[Keep existing id]
    F --> J[v2ByPath map]
    H --> J
    I --> J
    J --> K[Map v1 project id → v2 project id]
    K --> L[Adopt workspace via v2Workspace.create]
Loading

Comments Outside Diff (1)

  1. apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx, line 120-125 (link)

    P1 cloudWorkspacesQuery.isPending is absent from the isLoading gate. The new deduplication in v2ProjectIdByV1Id depends on cloudWorkspacesQuery.data, so if hostProjectListQuery settles first, the loading spinner disappears while projectIdsInCloud is still empty — the orphan row wins, the correct project ID is not yet picked, and a user who clicks Adopt in that window hits the same "Project not found" error the fix was meant to cure.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx
    Line: 120-125
    
    Comment:
    `cloudWorkspacesQuery.isPending` is absent from the `isLoading` gate. The new deduplication in `v2ProjectIdByV1Id` depends on `cloudWorkspacesQuery.data`, so if `hostProjectListQuery` settles first, the loading spinner disappears while `projectIdsInCloud` is still empty — the orphan row wins, the correct project ID is not yet picked, and a user who clicks Adopt in that window hits the same "Project not found" error the fix was meant to cure.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx:120-125
`cloudWorkspacesQuery.isPending` is absent from the `isLoading` gate. The new deduplication in `v2ProjectIdByV1Id` depends on `cloudWorkspacesQuery.data`, so if `hostProjectListQuery` settles first, the loading spinner disappears while `projectIdsInCloud` is still empty — the orphan row wins, the correct project ID is not yet picked, and a user who clicks Adopt in that window hits the same "Project not found" error the fix was meant to cure.

```suggestion
	const isLoading =
		projectsQuery.isPending ||
		workspacesQuery.isPending ||
		worktreesQuery.isPending ||
		hostProjectListQuery.isPending ||
		cloudWorkspacesQuery.isPending ||
		worktreeListQueries.some((q) => q.isPending);
```

Reviews (1): Last reviewed commit: "fix(desktop): prefer cloud-confirmed v2 ..." | Re-trigger Greptile

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6bfccdbe-4852-422e-b108-dbc346b79227

📥 Commits

Reviewing files that changed from the base of the PR and between f3ff72b and 24adbb5.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx

📝 Walkthrough

Walkthrough

The v2 project mapping logic in the import workspace page is refactored to prefer v2 IDs already present in cloud workspaces when duplicate repo paths exist. The memo dependency array and loading state are updated to account for cloud workspace query status.

Changes

V1 to V2 Project Mapping with Cloud Workspace Preference

Layer / File(s) Summary
Core Logic
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx (lines 55–75)
v2ProjectIdByV1Id memo now builds a v2ByPath map that prefers v2 IDs from cloud workspaces when duplicate repoPaths exist, then remaps v1 projects to their corresponding v2 IDs.
Dependencies & Loading State
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportWorkspacesPage/ImportWorkspacesPage.tsx (lines 55–75, 125)
useMemo dependency array updated to include cloudWorkspacesQuery.data; isLoading calculation now includes cloudWorkspacesQuery.isPending.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hops through clouds so high,
Finding v2 paths where duplicates lie.
When repos align, we pick what's near,
Cloud workspaces prioritized, crystal clear! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch debug-migration-db-gap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

cloudWorkspacesQuery was missing from isLoading, so a slow cloud response
let the modal render Adopt buttons before the preference logic had the
signal it needs to skip orphan host.db rows. The preference would then
fall back to first-seen and could still pick the orphan, hitting the
exact error this PR is meant to prevent.
@saddlepaddle saddlepaddle merged commit 61c6660 into main May 6, 2026
9 of 10 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request May 8, 2026
…opt (superset-sh#4137)

* fix(desktop): prefer cloud-confirmed v2 project in v1→v2 workspace adopt

When multiple host.db rows share a repo_path, the importer's repoPath→v2id
map was last-write-wins, so an orphan local project (e.g. left over from a
manual repair) could shadow the canonical id. Workspace adopt then called
v2Workspace.create with the orphan id and tripped the org-scope check with
"Project not found in this organization". Prefer ids that appear as a
projectId on the org's cloud workspace list, falling back to first-seen.

* fix(desktop): gate v1 import modal on cloud workspace list

cloudWorkspacesQuery was missing from isLoading, so a slow cloud response
let the modal render Adopt buttons before the preference logic had the
signal it needs to skip orphan host.db rows. The preference would then
fall back to first-seen and could still pick the orphan, hitting the
exact error this PR is meant to prevent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant