gastownhall/beads · error

quarantine dead backend record: %w

Error message

quarantine dead backend record: %w

What it means

The recorded backend PID was opened and verified as belonging to this workspace, but the process is dead; cleanup quarantines the stale record. This error wraps a failure of that quarantine rename, so the dead record stays in place and cleanup aborts.

Source

Thrown at internal/storage/dbproxy/proxy/endpoint.go:831

			pf.Pid,
			fmt.Errorf("root identity mismatch (record has %q, workspace has %q)", pf.RootID, expectedRootID),
			unverifiableProcessChecks{},
		)
	}

	handle, dead, err := openRecordedProcess(pf)
	if err != nil {
		return unverifiableProcessError(
			"backend cleanup",
			recordPath,
			pf.Pid,
			err,
			unverifiableProcessChecks{},
		)
	}
	if dead {
		if _, err := quarantineRecord(rootDir, server.PIDFileName, time.Now()); err != nil {
			return fmt.Errorf("quarantine dead backend record: %w", err)
		}
		return nil
	}
	if err := handle.Kill(); err != nil {
		_ = handle.Close()
		return fmt.Errorf("kill verified orphan backend pid %d from %s: %w", pf.Pid, recordPath, err)
	}
	// Close before waiting: an open handle on Windows keeps the dead PID
	// allocated, so procid.Verify would keep matching it and the exit wait
	// below would always time out.
	if err := handle.Close(); err != nil {
		return fmt.Errorf("close verified backend process handle for pid %d: %w", pf.Pid, err)
	}
	if err := waitForRecordedProcessExit(pf, backendExitTimeout); err != nil {
		return fmt.Errorf("wait for verified orphan backend pid %d: %w", pf.Pid, err)
	}
	if _, err := quarantineRecord(rootDir, server.PIDFileName, time.Now()); err != nil {
		return fmt.Errorf("quarantine orphan backend record: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix permissions on the workspace/dbproxy directory so the rename can succeed.
  2. Manually rename the record aside: mv <recordPath> <recordPath>.stale-$(date +%s) and retry.
  3. Stop other concurrent bd processes that may be touching the record.
  4. Address filesystem-level causes reported by the wrapped error (ENOSPC, EROFS).

Example fix

// before
Error: quarantine dead backend record: rename ...: file exists
// after
$ mv -f /ws/.beads/dbproxy/dolt-backend.pid /ws/.beads/dbproxy/dolt-backend.pid.stale-$(date +%s)
$ bd doctor
Defensive patterns

Strategy: fallback

Validate before calling

// Ensure quarantine is possible before cleanup:
probe := filepath.Join(rootDir, ".quarantine-probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil {
    return fmt.Errorf("workspace not writable, cleanup will fail: %w", err)
}
os.Remove(probe)

Try / catch

if err := cleanupOrphanBackend(rootDir); err != nil && strings.Contains(err.Error(), "quarantine dead backend record") {
    os.Rename(recordPath, recordPath+".stale-"+strconv.FormatInt(time.Now().Unix(), 10))
    err = cleanupOrphanBackend(rootDir)
}

Prevention

When it happens

Trigger: openRecordedProcess(pf) reports dead=true and quarantineRecord(rootDir, server.PIDFileName, time.Now()) fails at internal/storage/dbproxy/proxy/endpoint.go:829-831 (rename/permission/IO error).

Common situations: Quarantine directory unwritable or on a full/read-only filesystem; the record file was locked or concurrently modified by another bd process; ownership changed (record created by another user).

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/497e4eded2ef77ea. Report an issue: GitHub.