Skip to content

fix(desktop): use path.sep in migrateWorkspace nested-path guard#453

Open
HiddenPuppy wants to merge 5 commits intoclawwork-ai:mainfrom
HiddenPuppy:fix/382-migrate-workspace-sep
Open

fix(desktop): use path.sep in migrateWorkspace nested-path guard#453
HiddenPuppy wants to merge 5 commits intoclawwork-ai:mainfrom
HiddenPuppy:fix/382-migrate-workspace-sep

Conversation

@HiddenPuppy
Copy link
Copy Markdown
Collaborator

Replaces hardcoded '/' with sep from the path module so the nested-path check works correctly on Windows.

Jerome added 5 commits April 22, 2026 14:41
Fixes clawwork-ai#397

handleSave, handleTest, and handlePairingRetry all followed the pattern:
  setLoading(true) → await ipc() → setLoading(false)

If the IPC call threw (network error, preload exception, serialization
failure), the loading state was never reset and the button stayed stuck
on a greyed-out spinner.

Now each handler wraps the IPC call in try/finally so the loading flag
always resets, and catches errors with console.error + toast.error.
Fixes clawwork-ai#398

handleChangeWorkspace called setChangingWorkspace(true) → await IPC →
setChangingWorkspace(false) without try/catch. If the IPC threw (workspace
migration exception, invalid path, disk error), the button stayed stuck
spinning until Settings was closed.

Now both browseWorkspace and changeWorkspace are wrapped:
- browseWorkspace failure: logs + toast.error + early return
- changeWorkspace failure: logs + toast.error with error detail + finally
  resets loading state

Also wraps browseWorkspace for consistency, since it is also an IPC call
that can fail.
Fixes clawwork-ai#399

handleToggleEnabled and handleInstall both used the pattern:
  setXxx((prev) => new Set(prev).add(key))
  → await window.clawwork.xxx(...)
  → setXxx((prev) => remove key)

If the IPC call threw, the key was never removed from the toggling/installing
set and the button stayed spinning forever.

Now both handlers wrap the IPC call in try/finally so the set is always
cleaned up. Errors are caught, logged to console, and surfaced via toast.
…dater

Fixes clawwork-ai#400

handleNotificationToggle was computing the new state inline inside the
updateSettings argument: { notifications: { ...notifyState, [key]: value } }.
While not as severe as a setState updater, this pattern is still fragile
because it relies on the captured notifyState closure. If React re-renders
or batches updates, the stale closure could overwrite concurrent changes.

Now the new state is computed into a local  variable first, then
passed to updateSettings. This is cleaner, easier to read, and avoids any
potential issues with stale closures or double-invocation in Strict Mode.
Replaces hardcoded '/' with 'sep' from the path module so the
nested-path check works correctly on Windows.

- Fixes clawwork-ai#382
- Adds unit tests for migrateWorkspace and initWorkspace
@HiddenPuppy HiddenPuppy requested a review from samzong as a code owner April 23, 2026 05:42
@github-actions
Copy link
Copy Markdown
Contributor

Hi @HiddenPuppy,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request improves the robustness of the desktop application by addressing cross-platform path handling issues and enhancing error management in the UI layer. By replacing hardcoded path separators and implementing structured error handling for asynchronous tasks, the application becomes more resilient to environment-specific pathing and unexpected runtime failures.

Highlights

  • Cross-platform path compatibility: Updated the workspace migration logic to use path.sep instead of a hardcoded forward slash, ensuring correct behavior on Windows.
  • Improved error handling: Wrapped various asynchronous operations in UI components with try-catch blocks to provide better feedback and prevent unhandled promise rejections.
  • New unit tests: Added comprehensive unit tests for migrateWorkspace and initWorkspace to verify path validation and directory creation logic.
Ignored Files
  • Ignored by pattern: .github/workflows/** (6)
    • .github/workflows/ci-bot.yml
    • .github/workflows/e2e.yml
    • .github/workflows/pr-check.yml
    • .github/workflows/release.yml
    • .github/workflows/update-homebrew.yml
    • .github/workflows/website.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves the robustness of the settings sections by implementing try-catch-finally blocks for asynchronous operations, ensuring that loading states are correctly reset and errors are properly logged and displayed. It also updates workspace migration to use platform-specific path separators and introduces a new test suite for workspace initialization. Feedback was provided regarding the path comparison logic in the workspace migration, specifically to handle filesystem roots where trailing separators might cause incorrect prefix matching.

const resolvedOld = resolve(oldPath);
const resolvedNew = resolve(newPath);
if (resolvedNew.startsWith(resolvedOld + '/') || resolvedNew === resolvedOld) {
if (resolvedNew.startsWith(resolvedOld + sep) || resolvedNew === resolvedOld) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current path comparison logic fails when the workspace is located at the root of a drive or filesystem (e.g., C:\ on Windows or / on Linux). In such cases, path.resolve returns a path that already ends with a separator. Appending another sep creates a prefix like C:\\ or //, which causes startsWith to fail for subdirectories (e.g., C:\Users does not start with C:\\). Using a conditional check for the trailing separator ensures the prefix is correctly formed for both root and non-root paths. Additionally, note that startsWith is case-sensitive, which might be an issue on Windows if paths are provided with inconsistent casing.

Suggested change
if (resolvedNew.startsWith(resolvedOld + sep) || resolvedNew === resolvedOld) {
if (resolvedNew.startsWith(resolvedOld.endsWith(sep) ? resolvedOld : resolvedOld + sep) || resolvedNew === resolvedOld) {

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.

[Bug] migrateWorkspace path check uses hardcoded '/' separator, bypassed on Windows

1 participant