gastownhall/beads · error

quarantine proxy record

Error message

quarantine proxy record: %w

What it means

quarantineForSpawn wraps failures from quarantineRecord, which renames the existing proxy pidfile to <name>.stale-<unix-ts> before spawning a fresh proxy. The rename step failed, so the stale record still blocks the workspace and the restart is aborted.

Solutions

  1. Check write permission on the workspace root (the pidfile's directory) for the current user
  2. Re-run the command — the race is transient; quarantineRecord retries with later timestamps
  3. On Windows, exclude the workspace from AV/indexer file locking or close tools holding the pidfile open
  4. Manually move the pidfile aside (mv <root>/.beads/proxy.pid <root>/.beads/proxy.pid.stale-manual) and retry
  5. Check the wrapped os.Rename error (errors.Unwrap) for EXDEV/EACCES/EROFS and fix the underlying cause

Example fix

// before
target, err := quarantineRecord(rootDir, PIDFileName, time.Now())
if err != nil {
    return fmt.Errorf("quarantine proxy record: %w", err)
}
// after
target, err := quarantineRecord(rootDir, PIDFileName, time.Now())
if err != nil {
    if errors.Is(err, fs.ErrPermission) {
        log.Printf("workspace not writable for quarantine; retrying as %s", os.Geteuid())
    }
    return fmt.Errorf("quarantine proxy record: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if fi, err := os.Stat(pidfile.Path(root, PIDFileName)); err == nil && !fi.Mode().IsRegular() {
    return fmt.Errorf("proxy pidfile %s is not a regular file", pidfile.Path(root, PIDFileName))
}
if f, err := os.OpenFile(root, os.O_WRONLY, 0); err != nil {
    return fmt.Errorf("workspace root not writable: %w", err)
} else { f.Close() }

Try / catch

err := quarantineForSpawn(root, discovery)
for i := 0; err != nil && strings.Contains(err.Error(), "quarantine proxy record") && i < 2; i++ {
    time.Sleep(100 * time.Millisecond)
    err = quarantineForSpawn(root, discovery)
}

Prevention

When it happens

Trigger: The pidfile's containing directory is not writable, the source pidfile vanished or was replaced mid-rename, or the target stale path was created by a racing process between Lstat and Rename.

Common situations: Read-only workspace or NFS volume with permission issues; two bd processes racing to restart the proxy; antivirus/indexer temporarily locking the file on Windows (rename denied); disk full for metadata updates.

Related errors


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

Appendix: source

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

		)
	case adoptionUnverifiable:
		log.Printf(
			"dbproxy: proxy identity at %s could not be verified (%v); quarantining only its record under proxy.lock and starting a fresh proxy",
			pidfile.Path(rootDir, PIDFileName), discovery.err,
		)
	case adoptionLegacy:
		log.Printf(
			"dbproxy: quarantining legacy proxy record %s; a pre-upgrade proxy may still be running and must be stopped with the old bd binary if it does not idle-exit",
			pidfile.Path(rootDir, PIDFileName),
		)
	case adoptionMalformed:
		log.Printf("dbproxy: quarantining malformed proxy record %s (%v) before restart", pidfile.Path(rootDir, PIDFileName), discovery.err)
	default:
		return fmt.Errorf("cannot spawn from proxy discovery status %s", discovery.status)
	}
	target, err := quarantineRecord(rootDir, PIDFileName, time.Now())
	if err != nil {
		return fmt.Errorf("quarantine proxy record: %w", err)
	}
	log.Printf("dbproxy: preserved proxy record as %s", target)
	return nil
}

func quarantineRecord(rootDir, name string, now time.Time) (string, error) {
	source := pidfile.Path(rootDir, name)
	for stamp := now.Unix(); ; stamp++ {
		target := filepath.Join(rootDir, name+".stale-"+strconv.FormatInt(stamp, 10))
		if _, err := os.Lstat(target); err == nil {
			continue
		} else if !errors.Is(err, fs.ErrNotExist) {
			return "", fmt.Errorf("inspect quarantine target %s: %w", target, err)
		}
		if err := os.Rename(source, target); err != nil {
			return "", fmt.Errorf("rename %s to %s: %w", source, target, err)
		}
		return target, nil

View on GitHub (pinned to 71377f2769)