This repository was archived by the owner on Aug 6, 2026. It is now read-only.
Repository navigation
fix(code): chmod read-only subtrees before deleting worktrees - #1993
Merged
Merged
Conversation
Worktrees that ran any flox/Go workflow accumulate a module cache under .flox/cache/go/pkg/mod with every directory marked 0555. Plain fs.rm cannot unlink entries from those parents, so archive and suspend would fail with EACCES, the rollback would undo the archive row, and the task would reappear in the sidebar. Add forceRemove() to walk the tree restoring write bits on EACCES/EPERM and retry, then route every worktree-deletion call site through it. Generated-By: PostHog Code Task-Id: aa517cb8-e2ed-4a1c-bf8e-e592c652d690
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/git/src/utils.test.ts:28-67
**Prefer parameterised tests**
The project style guide asks for parameterised tests. The three `it` blocks ("removes a writable tree", "is a no-op for a missing path", and "removes a tree with read-only directories") share the same arrange-act-assert shape and could be expressed as a single `it.each` table, eliminating the repeated `workDir` / `forceRemove` / `fileExists` boilerplate.
### Issue 2 of 2
packages/git/src/utils.test.ts:19-26
**`afterEach` cleanup doesn't handle read-only subdirectories**
If `forceRemove` throws mid-way through the read-only test (leaving `yaml.v3@v3.0.1` still present with mode `0555`), `afterEach` does `chmod(workDir, 0o700)` — but only on `workDir` itself, not on its nested read-only children. The subsequent `rm(workDir, { recursive: true, force: true })` would then fail with `EACCES`, and the error is silently swallowed by `.catch(() => {})`, leaving a temp directory behind. Using `forceRemove` here instead closes the gap:
```suggestion
afterEach(async () => {
if (workDir) {
await forceRemove(workDir).catch(() => {});
workDir = undefined;
}
});
```
Reviews (1): Last reviewed commit: "fix(code): chmod read-only subtrees befo..." | Re-trigger Greptile |
jonathanlab
approved these changes
May 4, 2026
Use forceRemove in afterEach so cleanup handles read-only subdirs the same way the code under test does. Collapse the two tree-removal cases into a single it.each table to reduce boilerplate. Generated-By: PostHog Code Task-Id: aa517cb8-e2ed-4a1c-bf8e-e592c652d690
Silently swallowing these errors made it impossible to diagnose cases where forceRemove's chmod pass itself failed (e.g. immutable flags or ownership mismatches). Warn to console so the failure shows up in app logs without breaking the flow. Generated-By: PostHog Code Task-Id: aa517cb8-e2ed-4a1c-bf8e-e592c652d690
richardsolomou
enabled auto-merge (squash)
May 4, 2026 11:48
richardsolomou
disabled auto-merge
May 4, 2026 11:48
richardsolomou
enabled auto-merge (squash)
May 4, 2026 11:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Archiving (or suspending) a worktree that contained a Go module cache failed with
EACCES: permission denied, rmdir '.../posthog/.flox/cache/go/pkg/mod/<pkg>/...'. Go's modcache marks every cached directory0555, sofs.rmcannot unlink entries from those parents. The error propagated uparchiveTask, the rollback chain undid the archive row, and the task reappeared in the sidebar — so to the user the archive button just... did nothing..flox/exists in every flox-using worktree (even fresh ones, once anything is run), so this hit any task created in a flox-managed repo. Reported in Slack with multiple users blocked — "honestly kinda unusable".Changes
forceRemove(path)inpackages/git/src/utils.ts. Triesfs.rmonce with retries; onEACCES/EPERM, walks the tree restoring write bits (dirs0o700, files0o600) and retries. Symlinks are skipped vialstatso we don't chmod through them.forceRemove:packages/git/src/worktree.ts— fallback whengit worktree remove --forceitself fails (it hits the same EACCES on the modcache and triggers the fallback path).packages/git/src/sagas/worktree.ts— three rollback / execute spots inCreateWorktreeSaga,CreateWorktreeForBranchSaga,DeleteWorktreeSaga.apps/code/src/main/services/archive/service.ts— parent-dir cleanup afterdeleteWorktree(both archive and rollback paths).apps/code/src/main/services/suspension/service.ts— same pattern indeleteWorktreeOnDisk.How did you test this?
packages/git/src/utils.test.tsreproduces the bug: builds a directory tree shaped like a Go modcache (yaml.v3@v3.0.1/.github/...) with parent dirs at0555, asserts plainfs.rmrejects withEACCES, then assertsforceRemovesucceeds. Also covers the empty-tree and missing-path cases.node:fs/promisesthatforceRemoveneeds (lstat,chmod,readdir).pnpm --filter code test— 1007/1007 pass.pnpm --filter code typecheck— clean.pnpm --filter @posthog/git typecheck— clean.pnpm format/pnpm lint— clean.Publish to changelog?
no
Created with PostHog Code