gastownhall/beads · warning

remove expired quarantine %s: %w

Error message

remove expired quarantine %s: %w

What it means

sweepOldQuarantines removes .stale-<stamp> pidfile records older than quarantineRetention; this error wraps os.Remove failures for expired entries. Errors are accumulated and joined, so one bad file does not stop the sweep, but any failure surfaces here.

Source

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

		if entry.IsDir() {
			continue
		}
		var stampText string
		for _, prefix := range prefixes {
			if strings.HasPrefix(entry.Name(), prefix) {
				stampText = strings.TrimPrefix(entry.Name(), prefix)
				break
			}
		}
		if stampText == "" {
			continue
		}
		stamp, err := strconv.ParseInt(stampText, 10, 64)
		if err != nil || stamp >= cutoff {
			continue
		}
		if err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) {
			errs = append(errs, fmt.Errorf("remove expired quarantine %s: %w", entry.Name(), err))
		}
	}
	return errors.Join(errs...)
}

func cleanupOrphanBackend(rootDir string) error {
	recordPath := pidfile.Path(rootDir, server.PIDFileName)
	pf, readErr := pidfile.Read(rootDir, server.PIDFileName)

	childLockPath := filepath.Join(rootDir, server.LockFileName)
	childLock, lockErr := util.TryLock(childLockPath)
	switch {
	case lockErr == nil:
		childLock.Unlock()
	case lockfile.IsLocked(lockErr):
		pid := 0
		if pf != nil {
			pid = pf.Pid

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix ownership/permissions of the stale files: chown/chmod the workspace or remove them manually (rm <root>/*.stale-*)
  2. Re-run as the user that owns the stale records, or align user namespaces in containers
  3. On Windows, close tools/AV holding the file or add the workspace to exclusions
  4. Ignore if benign — the sweep error is non-fatal to spawning and the expired files can be cleaned manually

Example fix

// before
if err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) {
    errs = append(errs, fmt.Errorf("remove expired quarantine %s: %w", entry.Name(), err))
}
// after
if err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) && !errors.Is(err, fs.ErrPermission) {
    errs = append(errs, fmt.Errorf("remove expired quarantine %s: %w", entry.Name(), err))
}
Defensive patterns

Strategy: try-catch

Try / catch

if err := sweepOldQuarantines(root, time.Now()); err != nil {
    // joined errors: log and continue; spawn is still valid without the sweep
    log.Printf("quarantine sweep skipped: %v", err)
}

Prevention

When it happens

Trigger: os.Remove on an expired quarantine file fails with a non-ErrNotExist error during spawnAndHandoff's retention sweep — typically permission denied or the file being held open by another process.

Common situations: Stale quarantine files owned by a different user (root-created records, then running bd as a normal user); AV/indexer holding the old file open on Windows; read-only remount of the workspace.

Related errors


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