gastownhall/beads · error
discover proxy from %s under lock: %w
Error message
discover proxy from %s under lock: %w
What it means
Same PID-record I/O failure as the lock-free discovery error, but detected after this caller successfully acquired proxy.lock and re-read the record. This proves the record was unreadable even while holding the exclusive lock, ruling out a concurrent replacement race, so the library returns immediately instead of spawning. The wrapped cause is preserved for errors.Is/As inspection.
Source
Thrown at internal/storage/dbproxy/proxy/endpoint.go:246
case adoptionAdopted:
return adoptedEndpoint(rootDir, want, discovery)
case adoptionIOErr:
return Endpoint{}, fmt.Errorf("discover proxy from %s: %w", pidfile.Path(rootDir, PIDFileName), discovery.err)
}
lock, err := util.TryLock(filepath.Join(rootDir, LockFileName))
switch {
case err == nil:
// Re-read under proxy.lock. Another opener may have replaced the
// record after our lock-free discovery.
discovery = readAndDial(rootDir)
if discovery.status == adoptionAdopted {
lock.Unlock()
return adoptedEndpoint(rootDir, want, discovery)
}
if discovery.status == adoptionIOErr {
lock.Unlock()
return Endpoint{}, fmt.Errorf("discover proxy from %s under lock: %w", pidfile.Path(rootDir, PIDFileName), discovery.err)
}
markerActive, markerErr := inspectSpawnMarkerLocked(rootDir)
if markerErr != nil {
lock.Unlock()
return Endpoint{}, markerErr
}
if markerActive {
lock.Unlock()
lastSpawnErr = nil
// This break exits the switch only; the outer discovery loop
// continues with its normal bounded poll.
break
}
var ep Endpoint
ep, lastSpawnErr = spawnAndHandoff(rootDir, opts, deadline, stopEpoch, lock, discovery)
if lastSpawnErr == nil {View on GitHub (pinned to 71377f2769)
Solutions
- Fix read permissions on the pidfile for the current user (chown/chmod)
- If the record is stale, remove it manually and retry the operation
- Check for a read-only or full filesystem on the workspace mount
- Run under the same user account that originally created the proxy
Example fix
// before error: discover proxy from /repo/.beads/proxy.pid under lock: permission denied // after $ chmod u+r /repo/.beads/proxy.pid # or rm -f if stale $ bd ready
Defensive patterns
Strategy: validation
Validate before calling
// Under your own coordination, verify the record is readable before calling open
info, err := os.Stat(filepath.Join(rootDir, "proxy.pid"))
if err == nil && info.Mode().Perm()&0o400 == 0 {
os.Chmod(filepath.Join(rootDir, "proxy.pid"), 0o644)
} Prevention
- Standardize umask/permissions when creating workspace files
- Do not mix root and non-root bd runs in the same clone
- Monitor for read-only remounts on CI runners
When it happens
Trigger: GetCreateDatabaseProxyServerEndpoint acquired proxy.lock (no other opener held it), re-ran readAndDial, and the pidfile read still failed with an I/O error — e.g. the record exists but is unreadable due to permissions or filesystem errors.
Common situations: Mixed-UID ownership of the .beads workspace (agent runs as different user than initial setup); read-only bind mounts in CI containers; corrupted record from a partial write by an older binary.
Related errors
- discover proxy from %s: %w
- probe proxy lock: %w
- legacy proxy record %s is protected by held lock %s; stop th
- read proxy stop epoch under lock: %w
- discover spawned proxy: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5a271f15387516da.
Report an issue: GitHub.