nanocoai/nanoclaw · warning

Failed to clean up orphaned containers

Error message

Failed to clean up orphaned containers

What it means

During startup residue reaping, the host failed while removing orphaned Docker containers (labeled for this install but not matching any session). Those orphans keep running until the next successful sweep.

Source

Thrown at src/drivers/docker-driver.ts:349

        'status=exited',
        '--filter',
        'status=created',
        '--filter',
        'status=dead',
        '--format',
        '{{.Names}}',
      ]);
      const stale = out.trim().split('\n').filter(Boolean);
      for (const name of stale) {
        try {
          this.#cli.run(['rm', '--force', validateRuntimeName(name, 'container')]);
        } catch {
          /* already gone */
        }
      }
      if (stale.length > 0) log.info('Removed orphaned containers', { count: stale.length, names: stale });
    } catch (err) {
      log.warn('Failed to clean up orphaned containers', { err });
    }

    // Pre-seam residue: containers spawned before the driver seam carry the
    // install label but not the session label, so `listSessions` cannot see
    // them — they can be neither adopted nor matched to a session. Left alone
    // they would run forever AND race a freshly-named replacement for the same
    // session directory. Stopping them is exactly what the old
    // `cleanupOrphans()` did to every container on every start.
    try {
      const out = this.#cli.run([
        'ps',
        '--filter',
        `label=${LABELS.install}=${installSlug}`,
        '--format',
        `{{.Names}}|{{.Label "${LABELS.session}"}}`,
      ]);
      const preSeam = out
        .trim()

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Run `docker ps -a --filter label=<install-label>` and inspect leftovers
  2. Remove stragglers manually: `docker rm -f <name>`
  3. Restart nanoclaw so the next sweep retries
  4. Ensure only one host instance runs
Defensive patterns

Strategy: retry

Validate before calling

const orphans = execSync("docker ps -aq --filter label=<install-label>").toString().trim();

Try / catch

try { await reap(); } catch { /* next sweep retries; manual docker rm as fallback */ }

Prevention

When it happens

Trigger: The docker rm / list calls inside the orphan-cleanup block throw — daemon hiccup, container already being removed by another process, or name validation rejecting a weird container name.

Common situations: Two nanoclaw instances started concurrently, Docker restart mid-sweep, or leftover containers with unusual names from old installs.

Related errors


AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28). Data as JSON: /api/errors/c6c4226833b36bb8. Report an issue: GitHub.