Error instead of silently failing when browsing an unreachable environment#4590
Conversation
…ble environment The add-project browser resolves paths on the selected environment's filesystem, but never read the browse query's error. Against an environment the client cannot reach, the result is a silent dead end: the directory list renders an empty "Directories" group that is indistinguishable from an empty directory, no reason is shown anywhere, and the submit button stays enabled — pressing Enter then does nothing at all, with no feedback. Add `resolveBrowseAvailability`, which maps the environment's connection phase plus any browse error onto an explicit availability verdict, and use it to fail closed: - the browse RPC is not issued unless the environment is connected; - `canSubmitBrowsePath` is false when unavailable, disabling the Enter path, the submit button, and the clone-destination step. This also withholds the "create this folder and add it as a project" affordance, so the UI can never offer to create a directory on a host it failed to inspect; - the reason renders in the results empty state instead of a blank list. `handleAddProjectForEnvironment` also refuses with an explicit toast when the target environment is not connected, which covers the desktop folder-picker entry point that bypasses the browse UI entirely. The composer's @-path mention search dropped its error the same way, so an unreachable environment rendered "No matching files or folders" — a definitive-sounding answer to a question we never got to ask. It now surfaces the actual failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 93f2a23. Configure here.
ApprovabilityVerdict: Approved This is a well-scoped UX improvement that adds proper error messages when browsing an unreachable environment. The changes are self-contained with comprehensive test coverage, involving pure logic additions and UI error display without modifying core business logic. You can customize Macroscope's approvability policy. Learn more. |
…rowsing an unreachable environment) # Conflicts: # apps/web/src/components/CommandPalette.logic.test.ts # apps/web/src/components/CommandPalette.tsx
Adds pingdotgg#4590 to the thread-picker group rather than the main manifest: it edits the same CommandPalette trio, and specifically the browse/submit region that pingdotgg#4257 and pingdotgg#4426 also touch, so the combination resolves once against upstream main instead of being re-derived every refresh. Group rebuilt (reproduce) to b15922f and repinned in stack.toml; main stack refreshed. The group rebuild reproduced tree bad6ae3 across two independent runs, and the assembled tree keeps every pingdotgg#4590 gating site plus the composer path-search error. The one non-mechanical resolution: the group had already extracted the palette empty-state ternary into `contextualEmptyStateMessage` + `resolveCommandPaletteEmptyStateMessage`, so pingdotgg#4590's inline branch was rewritten onto that helper instead of taking either side verbatim.
…se errors Review caught a regression in the previous commit: treating any browse error as Unavailable made canSubmitBrowsePath false, which killed Create & Add on a perfectly reachable host. The server returns read_directory_failed whenever readdir on the parent fails, and only EACCES/EPERM are swallowed to an empty listing -- ENOENT propagates. So typing a folder that does not exist yet, which is precisely what Create & Add exists for, produced a browse error and the new gate refused to submit. Verified end to end: on a connected environment "~/brand-new-folder-xyz/" now shows an enabled "Create & Add", creates the directory, and adds the project. Availability is now derived from the connection phase alone. A browse failure on a reachable host says nothing about whether the environment can be reached, so it no longer participates. Also drop connectionStatusText from the add-project guard. It renders the bare phase word, so refusing an add against a non-connected environment produced "Failed to add project — Available". The toast now reuses the same availability verdict as the browser and reads "<environment> isn't connected."

What Changed
The add-project browser (
⌘K → Add project → Local folder) resolves paths on the selected environment's filesystem viafilesystemEnvironment.browse, but never read that query's error. This adds an explicit availability check and fails closed instead of failing silently.resolveBrowseAvailabilityinCommandPalette.logic.tsmaps the environment's connection phase (available/offline/connecting/reconnecting/error/connected) onto anAvailable|Unavailable { message }verdict, carrying the underlying reason when there is one. It is keyed on reachability only — a browse failure on a reachable host means the path does not exist yet (the server returnsread_directory_failedfor a missing parent), which is exactly the Create & Add case, so it must not gate submission.connected.canSubmitBrowsePathis false when unavailable, which disables the Enter path, the submit button, and the clone-destination step (they share it). This also withholds the "create this folder and add it as a project" affordance, so the UI can never offer to create a directory on a host it failed to inspect.handleAddProjectForEnvironmentrefuses with an explicit toast when the target environment is not connected, reusing the same verdict so the toast states the reason rather than a bare status word. This is the layer that covers the desktop folder-picker entry point, which bypasses the browse UI entirely.ChatComposer's@-path mention search dropped its error the same way, so an unreachable environment rendered "No matching files or folders." That reads as a definitive answer to a question we never got to ask; it now surfaces the actual failure.Why
Browsing resolves paths on a machine that may not be reachable, so "no entries" and "could not ask" are very different answers that looked identical.
Reproduced against a paired remote environment that was then killed: the palette rendered an empty Directories group indistinguishable from an empty directory, showed no reason anywhere, and left the Add button enabled. Pressing Enter did nothing at all — no toast, no error, no state change. The failure was entirely invisible.
FileBrowserPanelandFilePreviewPanelalready render.errorfor project file reads, so the add-project browser and the composer path search were the outliers rather than the convention.UI Changes
Both captures are the same flow —
Add project→ the remote environment →Local folder→~/— against a paired remote whose backend was killed.Before: empty list, no reason, Add enabled, Enter silently does nothing.
After:
Reconnecting to railbird-sf. Reason: Failed to fetch remote environment endpoint http://127.0.0.1:47319/.well-known/t3/environment (HttpClientError: Transport error ...), Add disabled.Verified live in the web app against two
t3 serveinstances: the second was paired as a remote environment, confirmedConnected, then killed to produce the unreachable state.Checklist
Validation:
vp test run apps/web/src/components/CommandPalette.logic.test.ts(14 tests, 9 new)vp run --filter @t3tools/web typecheck(no errors in changed files)vp linton all four changed files (no new findings)vp fmt --checkon all four changed filesNote
Low Risk
UI and client-side guardrails around filesystem browse/add flows; no auth or data-model changes, with behavior covered by new unit tests.
Overview
Unreachable environments no longer look like empty folders when adding projects or searching
@paths.Adds
resolveBrowseAvailabilityto map environment connection phase (and optional connection error text) to Available vs Unavailable messages. Browse stays available when connected even if directory read fails (so “create folder & add” still works).In the command palette add-project browse flow, the filesystem browse RPC runs only when the target environment is connected; otherwise the results area shows the availability message, directory lists are hidden, and Add / Create & Add / clone destination submission is disabled.
handleAddProjectForEnvironment(including the native folder picker) shows an error toast with the same message instead of attempting the add.ChatComposer@path search now shows the workspace lookup error in the empty menu state instead of “No matching files or folders.”Reviewed by Cursor Bugbot for commit 429e392. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Show error instead of silently failing when browsing an unreachable environment
resolveBrowseAvailabilityin CommandPalette.logic.ts that returns anAvailable/Unavailableverdict with a user-facing message based on the environment's connection phase and error reason.handleAddProjectForEnvironmentnow shows a toast error with a specific availability message instead of attempting an operation that will fail.Macroscope summarized 429e392.
Review follow-up (429e392)
Bugbot caught two issues on the first commit; both are fixed.
Browse errors blocked folder creation (high). Real regression, and my fault for unit-testing that branch instead of exercising it.
WorkspaceEntries.browseonly swallowsEACCES/EPERMto an empty listing —ENOENTpropagates asread_directory_failed. Treating that asUnavailablemadecanSubmitBrowsePathfalse, so Create & Add could never create a folder that did not already exist. Availability is now keyed on connection phase alone. Verified end to end: on a connected environment~/brand-new-folder-xyz/shows an enabled Create & Add, and Enter creates the directory and adds the project. Regression test added pinningconnected+ browse error toAvailable.Toast used status, not reason (medium).
connectionStatusTextrenders the bare phase word, so the refusal really did read "Failed to add project — Available". The guard now reuses the availability verdict and reads " isn't connected."