gastownhall/beads · error

quarantine proxy record: %w

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.

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)

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.