openclaw - 💡(How to fix) Fix [Bug]: Agent deletion leaves residuals in Docker bind mounts due to trash/movePathToTrash limitations [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#84121Fetched 2026-05-20 03:43:50
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
1
Author
Timeline (top)
labeled ×2closed ×1commented ×1

In Docker environments where the .openclaw directory is mounted as a volume or bind mount, deleting an agent often leaves physical directories behind (workspace/, agents/, sessions/).

This happens for two reasons:

  1. CLI Path: src/commands/onboard-helpers.ts's moveToTrash implementation only attempts to call the trash binary. Since trash-cli is missing from the official Docker image (Issue #83459), it fails and does nothing.
  2. Gateway Path: While the Gateway uses movePathToTrash (from @openclaw/fs-safe), this helper sometimes fails or is less robust when moving directories across filesystem boundaries (e.g., from a bind mount to the container's root trash) compared to the system-level trash-cli (which correctly handles .Trash-1000 at the mount point).

Root Cause

In Docker environments where the .openclaw directory is mounted as a volume or bind mount, deleting an agent often leaves physical directories behind (workspace/, agents/, sessions/).

This happens for two reasons:

  1. CLI Path: src/commands/onboard-helpers.ts's moveToTrash implementation only attempts to call the trash binary. Since trash-cli is missing from the official Docker image (Issue #83459), it fails and does nothing.
  2. Gateway Path: While the Gateway uses movePathToTrash (from @openclaw/fs-safe), this helper sometimes fails or is less robust when moving directories across filesystem boundaries (e.g., from a bind mount to the container's root trash) compared to the system-level trash-cli (which correctly handles .Trash-1000 at the mount point).

Code Example

async function moveToTrashBestEffort(pathname: string): Promise<void> {
  // ... check existence ...
  try {
    // Try trash binary first (supports cross-device move via .Trash-1000)
    await runCommandWithTimeout(["trash", pathname], { timeoutMs: 5000 });
  } catch {
    try {
      // Fallback to JS library
      await movePathToTrash(pathname);
    } catch {
      // Best-effort
    }
  }
}
RAW_BUFFERClick to expand / collapse

Description

In Docker environments where the .openclaw directory is mounted as a volume or bind mount, deleting an agent often leaves physical directories behind (workspace/, agents/, sessions/).

This happens for two reasons:

  1. CLI Path: src/commands/onboard-helpers.ts's moveToTrash implementation only attempts to call the trash binary. Since trash-cli is missing from the official Docker image (Issue #83459), it fails and does nothing.
  2. Gateway Path: While the Gateway uses movePathToTrash (from @openclaw/fs-safe), this helper sometimes fails or is less robust when moving directories across filesystem boundaries (e.g., from a bind mount to the container's root trash) compared to the system-level trash-cli (which correctly handles .Trash-1000 at the mount point).

Steps to Reproduce

  1. Run OpenClaw in Docker with /root/.openclaw bind-mounted.
  2. Ensure trash-cli is NOT installed in the container (default state).
  3. Create and then delete an agent (either via CLI --force or Gateway UI).
  4. Observe that while the agent is removed from openclaw.json, the physical directories remain in ~/.openclaw.

Expected Behavior

Agent deletion should be a "best-effort" but robust process that cleans up physical files even in cross-device/bind-mount scenarios.

Suggested Fix

  1. Add trash-cli to the official Docker image (as suggested in #83459).
  2. Implement a robust "Best Effort" trash logic that is shared between CLI and Gateway:
    • First attempt to use the system trash command (most robust for mounts).
    • Fall back to the JS movePathToTrash helper if the binary is missing or fails.
    • (Optional) Fall back to a simple rename/move or rm -rf if both trash methods fail and it's a forced deletion.

I've successfully resolved this locally by updating moveToTrashBestEffort in src/gateway/server-methods/agents.ts to prioritize the binary:

async function moveToTrashBestEffort(pathname: string): Promise<void> {
  // ... check existence ...
  try {
    // Try trash binary first (supports cross-device move via .Trash-1000)
    await runCommandWithTimeout(["trash", pathname], { timeoutMs: 5000 });
  } catch {
    try {
      // Fallback to JS library
      await movePathToTrash(pathname);
    } catch {
      // Best-effort
    }
  }
}

And similar logic should be applied to the CLI path in src/commands/onboard-helpers.ts.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: Agent deletion leaves residuals in Docker bind mounts due to trash/movePathToTrash limitations [1 comments, 2 participants]