gastownhall/beads · error
proxy.ForceStopUnverified: acquire %s: %w
Error message
proxy.ForceStopUnverified: acquire %s: %w
What it means
This error is returned by acquireForceStopLock when, after inspecting and signaling the unverified PID, re-attempting to take the workspace lock file fails with an error that is NOT 'lock is held' (lockfile.IsLocked(err) is false). That means TryLock itself failed — e.g. filesystem error creating/opening the lock file, permission problem, or path issue — rather than mere contention. The wrapped cause (%w) carries the underlying reason.
Source
Thrown at internal/storage/dbproxy/proxy/force_stop.go:294
time.Sleep(shutdownConfirmPoll)
}
}
func normalizeForceStopExecutable(name string) string {
name = strings.TrimSpace(filepath.Base(name))
name = strings.TrimSuffix(name, " (deleted)")
name = strings.TrimSuffix(strings.ToLower(name), ".exe")
return name
}
func acquireForceStopLock(lockPath string, deadline time.Time) (*util.Lock, error) {
for {
lock, err := util.TryLock(lockPath)
if err == nil {
return lock, nil
}
if !lockfile.IsLocked(err) {
return nil, fmt.Errorf("proxy.ForceStopUnverified: acquire %s: %w", lockPath, err)
}
if time.Now().After(deadline) {
return nil, fmt.Errorf("proxy.ForceStopUnverified: timeout acquiring %s after signaling", lockPath)
}
time.Sleep(shutdownConfirmPoll)
}
}
func quarantineForceStopRecord(
rootDir string,
pidName string,
record *pidfile.PidFile,
report *ForceStopReport,
) error {
current, err := pidfile.Read(rootDir, pidName)
if err != nil {
return fmt.Errorf("proxy.ForceStopUnverified: re-read %s: %w", report.RecordPath, err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause to identify the filesystem failure (permission denied, ENOENT, EROFS, ENOSPC) and fix the workspace directory state
- Restore write permissions on the workspace root: chmod u+w <rootDir> (and its parent) so the lock file can be created
- If the workspace was moved/renamed, re-run force-stop from the correct workspace path so lockPath resolves
- Confirm the process was actually stopped (ps -p <pid>), then quarantine the record manually (rename proxy.pid to proxy.pid.stale-<unix-timestamp>) to recover without the lock
Defensive patterns
Strategy: validation
Validate before calling
// Verify the workspace is writable and the lock path is creatable before force-stop:
lockPath := filepath.Join(rootDir, "proxy.lock")
if err := os.Chmod(rootDir, 0o755); err != nil { return err }
probe, err := os.OpenFile(lockPath, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil { return err }
probe.Close() Try / catch
report, err := proxy.ForceStopUnverified(rootDir)
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
// Non-contention lock failure: fix filesystem/permissions at pathErr.Path, then retry
}
} Prevention
- Run bd as a user with write access to the workspace root
- Do not move, rename, or make read-only a workspace while bd commands may run
- Keep the workspace on a local filesystem with working flock semantics (not NFS without proper lock support)
- Watch disk space; ENOSPC surfaces as this acquisition error rather than lock contention
When it happens
Trigger: Call ForceStopUnverified (`bd dolt stop --force`) on a record whose lock was held by another process (LockWasHeld=true path); after signaling the PID, the retry loop's util.TryLock(lockPath) returns a non-IsLocked error — e.g. read-only filesystem, deleted parent directory, or permission denied on the lock path.
Common situations: Workspace directory made read-only or moved while force-stop runs; another tool deleted/recreated the lock path mid-operation; running under a user without write permission to the workspace root; disk-full conditions preventing lock file creation.
Related errors
- writing lock info: %w
- clearing lock metadata: %w
- proxy.ForceStopUnverified: timeout acquiring %s after signal
- proxy.ForceStopUnverified: re-read %s: %w
- dolt path is not executable
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/812e8bedbedd4d9b.
Report an issue: GitHub.