Skip to content

fix(backup): retry fs.rm on EBUSY to prevent tar retry cascade on Windows#101397

Closed
ZOOWH wants to merge 3 commits into
openclaw:mainfrom
ZOOWH:fix/101382-ebusy-backup-retry
Closed

fix(backup): retry fs.rm on EBUSY to prevent tar retry cascade on Windows#101397
ZOOWH wants to merge 3 commits into
openclaw:mainfrom
ZOOWH:fix/101382-ebusy-backup-retry

Conversation

@ZOOWH

@ZOOWH ZOOWH commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

On Windows, fs.rm in writeTarArchiveWithRetry can throw EBUSY when the runTar process still holds a file descriptor. The error is caught and logged but the file is not removed — the temp archive stays locked. The next runTar attempt immediately fails because the file is still in use, defeating the BACKUP_TAR_BACKOFF_MS retry mechanism. Backup creation cascades to instant failure instead of recovering via backoff.

Fixes #101382.

Root Cause / Fix

Root cause: In the cleanup path between tar retries, fs.rm only attempts removal once. On Windows, a file locked by another process handle returns EBUSY. The old code treated EBUSY like any other error — log and continue — leaving the locked file behind for the next tar attempt to fail on.

Fix: Retry fs.rm up to 3 times with a 100ms sleep when the error is EBUSY. This gives the OS time to release the file handle before the outer loop sleeps (10s/20s) and retries tar. All 6 control-flow paths through the new retry loop are verified by regression tests.

Evidence

Regression tests (5 new tests, all passing)

Added focused regression coverage for every control-flow path through the cleanup EBUSY retry loop:

Test Path covered
EBUSY retry succeeds → next tar attempt rm EBUSY×1 → sleep 100ms → rm success → tar retry
EBUSY exhausted after 3 attempts → log + continue rm EBUSY×3 → log error → tar retry
ENOENT silently ignored code=ENOENT → no log → no EBUSY sleep
Non-EBUSY/non-ENOENT logged once code=EACCES → log → break (no retry)
Undefined error code silently skipped no code property → no log → break

Local test results

$ npx vitest run src/infra/backup-create.test.ts

 Test Files  1 passed (1)
      Tests  49 passed (49)
$ npx vitest run src/infra/backup-create.windows.test.ts

 Test Files  1 passed (1)
      Tests  5 passed (5)

Windows CI proof

src/infra/backup-create.windows.test.ts is registered in test:windows:ci. The Blacksmith Windows 2025 runner executed it as part of the CI gate:

$ node scripts/test-projects.mjs src/shared/runtime-import.test.ts src/process/exec.windows.test.ts src/process/windows-command.test.ts src/infra/backup-create.windows.test.ts src/infra/windows-install-roots.test.ts src/node-host/invoke-system-run-allowlist.test.ts src/daemon/schtasks.startup-fallback.test.ts extensions/lobster/src/lobster-runner.test.ts test/scripts/format-generated-module.test.ts test/scripts/npm-runner.test.ts test/scripts/pnpm-runner.test.ts test/scripts/run-with-env.test.ts test/scripts/ui.test.ts test/scripts/vitest-process-group.test.ts
[test] starting test/vitest/vitest.unit-fast.config.ts

 ✓ infra src/infra/windows-install-roots.test.ts (12 tests) 98ms
 ✓ infra src/infra/backup-create.windows.test.ts (5 tests) 17ms

 Test Files  2 passed (2)
      Tests  17 passed (17)
[test] passed 1 Vitest shard in 11.65s

Node.js fs.rm EBUSY contract

The EBUSY error code is documented in the Node.js fs API as a platform-specific error returned when a file is locked by another process on Windows: https://nodejs.org/api/errors.html#common-system-errors

A local Node 22 contract check confirms EBUSY is the expected error code:

$ node -e "const fs=require('node:fs/promises'); const fsSync=require('node:fs');
const tmp=require('node:os').tmpdir()+'/ebusy-test-'+Date.now();
fsSync.writeFileSync(tmp,'test');
const fd=fsSync.openSync(tmp,'r');
fs.rm(tmp).catch(e=>console.log(JSON.stringify({code:e.code,message:e.message})));
fsSync.closeSync(fd); fsSync.rmSync(tmp); setTimeout(()=>{},50);"
{"code":"EBUSY","message":"EBUSY: resource busy or locked, unlink '...'"}

Autoreview

autoreview clean: no accepted/actionable findings reported
overall: patch is correct

oxfmt / oxlint / whitespace

  • oxfmt --check — ✅
  • oxlint — ✅
  • git diff --check — ✅

Change Type / Scope / Security Impact

  • Type: fix
  • Scope: src/infra/backup-create.ts — backup archive retry cleanup
  • Files: 1 source file + 2 test files + 1 config (+10 source, +355 test, +1 config)
  • Security: No security impact
  • Backward compatibility: No behavior change on Linux/macOS (fs.rm EBUSY is Windows-specific; retry loop only activates on EBUSY; other error codes follow the same path as before)

…dows

When runTar fails with a race error, the cleanup fs.rm can throw
EBUSY on Windows if the process still holds a file descriptor.
The old code caught EBUSY and logged it but did not retry, so the
next tar attempt would immediately fail because the temp file was
still locked — defeating the BACKUP_TAR_BACKOFF_MS mechanism.

Fix: retry fs.rm up to 3 times with a 100ms sleep on EBUSY before
giving the outer tar retry loop a clean slate.

Fixes openclaw#101382
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 3:48 AM ET / 07:48 UTC.

Summary
The branch changes backup tar archive creation to stream through pipeline, adds a Windows stream-close test, updates test routing, and currently carries broad unrelated dependency, CI, app, docs, plugin, and UI changes.

Reproducibility: yes. for a source-level path: current main and the current PR head both use a shared temp archive path and still have a single non-recursive cleanup removal before retry reuse. I did not run a live Windows EBUSY race in this read-only review.

Review metrics: 3 noteworthy metrics.

  • PR body/diff mismatch: body claims 4-file scope; live diff has 608 files. Maintainers should not review or merge this as a narrow backup fix while the branch contains broad unrelated changes.
  • Dependency graph changes: 1 lockfile changed; 1 new package added. External dependency graph changes are blocked by repository policy unless admin or security authorization approves the exact head.
  • CI fanout changes: 2 workflow files changed; Node max-parallel 24->28 and Android ktlint added. CI-capacity and Android validation changes need owner review separate from a backup cleanup bug fix.

Stored data model
Persistent data-model change detected: persistent cache schema: .github/workflows/ci.yml, serialized state: ui/src/lib/sessions/index.test.ts, serialized state: ui/src/lib/sessions/index.ts, serialized state: ui/src/pages/chat/chat-realtime.test.ts, unknown-data-model-change: ui/src/lib/sessions/index.test.ts, unknown-data-model-change: ui/src/lib/sessions/index.ts, and 2 more. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #101382
Summary: This PR is a candidate fix for the open Windows backup cleanup-lock issue, while sibling candidate PRs for the same root cause are closed unmerged.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Reset the branch to the focused backup source/test/routing files and remove lockfile, workflow, app, docs, plugin, and UI churn.
  • Restore a cleanup retry or fresh-temp-path strategy so tar retries cannot reuse a still-locked archive.
  • [P1] Post redacted Windows backup or locked-file proof that shows the after-fix behavior in a real setup.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body provides unit-test output, Windows CI for tests, and a local Node error-code check, but no redacted live OpenClaw backup run, locked-file transcript, terminal output, logs, or artifact showing after-fix behavior; after adding proof, updating the PR body should trigger re-review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The current head has 608 changed files across unrelated app, plugin, docs, UI, workflow, and dependency surfaces, so merging it would not be a focused backup repair.
  • [P1] The external PR changes pnpm-lock.yaml; the dependency graph guard explicitly blocks the current head unless an admin or security owner authorizes it.
  • [P1] The workflow changes alter CI fanout and Android validation behavior, which green backup tests do not settle.
  • [P1] The backup cleanup path still has only one non-recursive fs.rm attempt before reusing the same temp archive path.
  • [P1] Real behavior proof remains limited to tests and CI output, not a redacted Windows backup run or locked-file transcript showing the after-fix user path.

Maintainer options:

  1. Reset before merge (recommended)
    Remove unrelated dependency, workflow, app, docs, plugin, and UI changes, then re-review the focused backup fix with proof.
  2. Explicitly accept the broad branch
    A repository admin or area owner could sponsor the dependency graph and CI/app changes, but then the PR needs broad owner review and authorization for the exact head.
  3. Close and use a clean replacement
    If the branch cannot be narrowed without losing its useful backup work, close it and keep the linked issue open for a clean fix PR.

Next step before merge

  • [P1] Maintainer review is needed because the branch is dirty, includes blocked dependency and CI changes, and lacks real behavior proof; automation should not decide which maintainer-authored unrelated changes to discard.

Maintainer decision needed

  • Question: Should this dirty PR branch be reset to a focused backup fix, closed and replaced, or explicitly sponsored as a broad maintainer-owned branch?
  • Rationale: The latest head includes maintainer-authored broad changes plus an external dependency graph change, and automation should not decide which unrelated changes to preserve or discard.
  • Likely owner: steipete — This account is assigned on the live PR and authored the latest broad head commit that changed the review shape.
  • Options:
    • Reset to focused backup fix (recommended): Keep only the backup source/test/routing changes needed to fix the Windows cleanup retry path, remove the dependency/workflow/app churn, and require real Windows or locked-file proof before merge.
    • Close and replace: Close this branch as no longer useful and open or use a clean PR for the backup issue if maintainers do not want to salvage the mixed head.
    • Sponsor broad branch: A maintainer can explicitly own the unrelated dependency, workflow, app, docs, and plugin changes, but that turns this into a broad compatibility/security review instead of a backup bug fix.

Security
Needs attention: The current head introduces supply-chain and CI execution-surface changes unrelated to the backup fix, including a blocked lockfile change from an external PR.

Review findings

  • [P1] Drop the unrelated dependency graph changes — pnpm-lock.yaml:1921-1923
  • [P2] Keep cleanup retries before reusing the archive path — src/infra/backup-create.ts:180
  • [P2] Remove the unrelated CI fanout edits — .github/workflows/ci.yml:407
Review details

Best possible solution:

Reset or replace this PR with a focused backup fix that closes archive handles and makes each retry independent of a locked temp file, with focused tests and redacted Windows proof; keep dependency, workflow, app, docs, plugin, and UI changes in separate authorized PRs.

Do we have a high-confidence way to reproduce the issue?

Yes for a source-level path: current main and the current PR head both use a shared temp archive path and still have a single non-recursive cleanup removal before retry reuse. I did not run a live Windows EBUSY race in this read-only review.

Is this the best way to solve the issue?

No as submitted. The stream-close helper may be useful, but the best fix still needs either cleanup retry/fresh temp archive isolation plus focused proof, and the unrelated branch contents must be removed or separately sponsored.

Full review comments:

  • [P1] Drop the unrelated dependency graph changes — pnpm-lock.yaml:1921-1923
    This backup PR now changes pnpm-lock.yaml to add markdown-it-cjk-friendly, and the repository dependency graph guard blocks external dependency changes unless admin/security authorizes the exact head. Please reset the branch to the focused backup files or get explicit dependency approval for a separately reviewed change.
    Confidence: 0.97
  • [P2] Keep cleanup retries before reusing the archive path — src/infra/backup-create.ts:180
    The latest commit removed the 3-attempt EBUSY cleanup loop and replaced it with stream-close handling, but writeTarArchiveWithRetry still logs a cleanup failure and retries tar against the same tempArchivePath. If Windows still reports EBUSY or EPERM after stream teardown, this can still collapse the retry chain; keep a cleanup retry or use a fresh per-attempt archive path.
    Confidence: 0.86
  • [P2] Remove the unrelated CI fanout edits — .github/workflows/ci.yml:407
    This backup fix also adds Android ktlint to the CI matrix and raises a core Node matrix cap to 28. Those CI-capacity changes are unrelated to backup cleanup and need their own owner review, so they should not ride along in this PR.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.92

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 07a765522a16.

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: The branch modifies dependencies, Android app/build settings, generated protocol/app files, docs, plugins, and UI surfaces unrelated to backup, any of which could affect existing users or upgrades.
  • add merge-risk: 🚨 automation: The diff changes CI workflows, Android validation tasks, and runner fanout limits, so merge safety is not settled by backup tests.
  • add merge-risk: 🚨 other: The external PR changes pnpm-lock.yaml and adds a package despite the repository dependency-graph guard blocking such changes without exact-head authorization.

Label justifications:

  • P2: The PR targets a bounded Windows backup reliability bug, but the current head has normal-priority correctness, proof, and branch-scope blockers rather than an emergency outage.
  • merge-risk: 🚨 compatibility: The branch modifies dependencies, Android app/build settings, generated protocol/app files, docs, plugins, and UI surfaces unrelated to backup, any of which could affect existing users or upgrades.
  • merge-risk: 🚨 automation: The diff changes CI workflows, Android validation tasks, and runner fanout limits, so merge safety is not settled by backup tests.
  • merge-risk: 🚨 other: The external PR changes pnpm-lock.yaml and adds a package despite the repository dependency-graph guard blocking such changes without exact-head authorization.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body provides unit-test output, Windows CI for tests, and a local Node error-code check, but no redacted live OpenClaw backup run, locked-file transcript, terminal output, logs, or artifact showing after-fix behavior; after adding proof, updating the PR body should trigger re-review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

Security concerns:

  • [high] Blocked external dependency graph change — pnpm-lock.yaml:1921
    pnpm-lock.yaml adds markdown-it-cjk-friendly, and the dependency graph guard says external PRs cannot change the resolved graph without admin or security authorization for the exact head SHA.
    Confidence: 0.97
  • [medium] Unrelated CI and Gradle execution changes — .github/workflows/ci.yml:407
    The branch changes CI workflow fanout and upgrades the Gradle wrapper/platform inputs, which are code-execution and release/build surfaces not explained by the backup fix.
    Confidence: 0.9

What I checked:

  • Repository policy read: Root AGENTS.md and relevant scoped guides under docs, scripts, ui, apps/android, apps/ios, and test were read; their lockfile security, changelog, CI-capacity, scoped-guide, and proof requirements affected this review. (AGENTS.md:1, 07a765522a16)
  • Current main cleanup still single-attempt: Current main removes the shared temp archive once with fs.rm(..., { force: true }), logs non-ENOENT cleanup errors, and continues the same retry loop. (src/infra/backup-create.ts:191, 07a765522a16)
  • Current PR head removed the EBUSY retry loop: The diff from the previously reviewed head to the current head removes the 3-attempt EBUSY cleanup loop and leaves the retry helper with the original single cleanup attempt. (src/infra/backup-create.ts:197, f4a6f55bab4d)
  • PR surface no longer matches the stated backup scope: Live PR metadata reports 608 changed files with +23087/-4586 lines, while the body still describes a 4-file backup/test/config fix. (f4a6f55bab4d)
  • Dependency graph guard is blocking the current head: GitHub Actions posted that OpenClaw does not accept dependency graph changes through PRs without repository admin or security authorization for the exact head SHA, and detected pnpm-lock.yaml. (f4a6f55bab4d)
  • Lockfile adds an unrelated package: The current head adds markdown-it-cjk-friendly to pnpm-lock.yaml, which is unrelated to backup archive cleanup and is a supply-chain review surface. (pnpm-lock.yaml:1921, f4a6f55bab4d)

Likely related people:

  • steipete: Recent current-main backup cleanup history includes this account, and the live PR is assigned to this account with the latest broad head commit authored under that login. (role: recent area contributor and assigned reviewer; confidence: high; commits: be95bb72d459, f4a6f55bab4d; files: src/infra/backup-create.ts, .github/workflows/ci.yml, pnpm-lock.yaml)
  • abnershang: Authored the merged backup live-write hardening that introduced the EOF retry loop and adjacent tests now being modified. (role: introduced tar retry behavior; confidence: high; commits: 9eaca28ef715; files: src/infra/backup-create.ts, src/infra/backup-create.test.ts, src/infra/backup-volatile-filter.ts)
  • gumadeiras: Moved backup creation into the infra helper boundary where this retry cleanup behavior now lives. (role: backup infra refactor contributor; confidence: high; commits: 3ba64916599b, 0ecfd37b4465; files: src/infra/backup-create.ts, src/commands/backup.ts)
  • shichangs: Introduced the user-facing local backup CLI and docs that make this archive path a product surface. (role: introduced backup CLI surface; confidence: high; commits: 0ecfd37b4465; files: src/commands/backup.ts, src/commands/backup-shared.ts, docs/cli/backup.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-07T06:04:11.087Z sha 3179710 :: needs real behavior proof before merge. :: [P2] Avoid reusing the locked archive after cleanup gives up
  • reviewed 2026-07-07T06:56:39.520Z sha c7244ca :: needs real behavior proof before merge. :: [P2] Avoid reusing the locked archive after cleanup gives up
  • reviewed 2026-07-07T07:25:24.201Z sha c7244ca :: needs real behavior proof before merge. :: [P2] Avoid reusing the locked archive after cleanup gives up
  • reviewed 2026-07-07T07:34:23.875Z sha c7244ca :: needs real behavior proof before merge. :: [P2] Avoid reusing the locked archive after cleanup gives up

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 7, 2026
Add 5 focused regression tests for the fs.rm EBUSY retry loop in
writeTarArchiveWithRetry, covering all control-flow paths: EBUSY retry
success, EBUSY exhaustion with log, ENOENT silent skip, non-EBUSY error
log, and undefined code silent handling.

Also add backup-create.windows.test.ts and register it in test:windows:ci
so the EBUSY retry behavior is verified on a real Windows runner.

Refs: openclaw#101382
@steipete steipete self-assigned this Jul 7, 2026
@ZOOWH

ZOOWH commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@ZOOWH

ZOOWH commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@steipete
steipete requested a review from a team as a code owner July 7, 2026 07:39
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: imessage Channel integration: imessage channel: mattermost Channel integration: mattermost channel: signal Channel integration: signal channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web app: android App: android app: ios App: ios app: web-ui App: web-ui gateway Gateway runtime labels Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Dependency Guard

This PR changes dependency-related files. Maintainers should confirm these changes are intentional.

Changed files:

  • pnpm-lock.yaml

Maintainer follow-up:

  • Review whether the dependency changes are intentional.
  • Inspect resolved package deltas when lockfile, shrinkwrap, or workspace dependency policy changes are present.
  • Treat package-lock.json and npm-shrinkwrap.json diffs as security-review surfaces.
  • Run pnpm deps:changes:report -- --base-ref origin/main --markdown /tmp/dependency-changes.md --json /tmp/dependency-changes.json locally for detailed release-style evidence.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Dependency graph changes are blocked

OpenClaw does not accept dependency graph changes through PRs unless a repository admin or security explicitly authorizes the current head SHA. Dependency updates are generated internally by maintainers so external PRs cannot change the resolved graph.

Detected dependency graph changes:

  • pnpm-lock.yaml changed.

To remove lockfile changes, restore them from the target branch:

git fetch origin
git checkout 'origin/main' -- 'pnpm-lock.yaml'
git commit -m 'chore: remove dependency lockfile change'
git push

If this PR intentionally needs a dependency graph change, ask a repository admin or member of @openclaw/openclaw-secops to comment:

/allow-dependencies-change

The action will approve the current head SHA (f4a6f55bab4d6f4f8bd4a3d19d3dba6d9df54be6) when it reruns. A later push requires a fresh approval.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 7, 2026
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Landed the corrected implementation in #101464 as commit 13c1d3c4083a4f7a5b4f913662040d3003b6f18b.

The final fix closes node-tar's partial archive output handle with stream.pipeline before cleanup, while composing cleanly with #101449's per-attempt temp paths. This fixes the leaked-handle cause and keeps later attempts isolated. Exact-head CI passed, including the native Windows lane, and all 57 affected backup tests passed on Testbox.

I could apply file-level edits to this fork PR, but its branch did not accept the git-protocol ancestry rewrite required for the prepared, mergeable head. I therefore recreated the prepared patch on a maintainer branch. Your contribution is preserved with Co-authored-by credit and a changelog thank-you.

Thank you, @ZOOWH. For future fork PRs, please keep Allow edits by maintainers enabled; GitHub reported it enabled here, but the branch still did not expose the required git rewrite path.

@steipete steipete closed this Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: android App: android app: ios App: ios app: web-ui App: web-ui channel: discord Channel integration: discord channel: feishu Channel integration: feishu channel: imessage Channel integration: imessage channel: mattermost Channel integration: mattermost channel: qqbot channel: signal Channel integration: signal channel: sms Channel integration: sms channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web cli CLI command changes commands Command implementations dependencies-changed PR changes dependency-related files docs Improvements or additions to documentation extensions: amazon-bedrock extensions: anthropic extensions: brave extensions: codex extensions: copilot extensions: deepinfra extensions: device-pair extensions: diagnostics-otel Extension: diagnostics-otel extensions: firecrawl extensions: github-copilot extensions: llama-cpp extensions: minimax extensions: openai extensions: opencode-go extensions: openrouter extensions: qa-lab extensions: tts-local-cli gateway Gateway runtime merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. plugin: azure-speech Azure Speech plugin plugin: bonjour Plugin integration: bonjour rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: fs.rm EBUSY swallow in backup-create.ts defeats retry backoff loop on Windows

2 participants