gastownhall/beads · error
read proxy stop epoch under lock: %w
Error message
read proxy stop epoch under lock: %w
What it means
spawnAndHandoff, while holding proxy.lock, re-reads the stop epoch file to confirm no concurrent 'stop' happened between the caller's initial read and the spawn. If readStopEpoch fails here (I/O error on the epoch file), the spawn is aborted and the read error is wrapped and returned. This guards against spawning a proxy that a concurrent stop already intended to tear down.
Source
Thrown at internal/storage/dbproxy/proxy/endpoint.go:322
func spawnAndHandoff(
rootDir string,
opts OpenOpts,
deadline time.Time,
stopEpoch string,
lock *util.Lock,
discovery adoptionResult,
) (Endpoint, error) {
handedOff := false
defer func() {
if !handedOff {
lock.Unlock()
}
}()
currentEpoch, err := readStopEpoch(rootDir)
if err != nil {
return Endpoint{}, fmt.Errorf("read proxy stop epoch under lock: %w", err)
}
if currentEpoch != stopEpoch {
return Endpoint{}, fmt.Errorf("%w for %s", errStartInterrupted, rootDir)
}
if err := quarantineForSpawn(rootDir, discovery); err != nil {
return Endpoint{}, err
}
if err := cleanupOrphanBackend(rootDir); err != nil {
return Endpoint{}, err
}
handedOff = true
child, err := forkExecChild(rootDir, opts, opts.Port, stopEpoch, lock)
if err != nil {
return Endpoint{}, fmt.Errorf("fork child: %w", err)
}
defer func() { _ = clearOwnSpawnMarker(rootDir, child.marker) }()View on GitHub (pinned to 71377f2769)
Solutions
- Retry the operation once the filesystem is readable; transient IO errors often clear
- Check permissions/health of the stop-epoch file in <rootDir> (ls -l, cat it manually)
- Ensure no concurrent bd stop/teardown is racing your spawn (serialize commands)
- Move the workspace off a failing/network filesystem if errors persist
Example fix
// before error: read proxy stop epoch under lock: open /repo/.beads/stop-epoch: permission denied // after $ chmod u+r /repo/.beads/stop-epoch $ bd ready
Defensive patterns
Strategy: retry
Validate before calling
// Verify the stop-epoch file is readable before spawning work
if _, err := os.ReadFile(filepath.Join(rootDir, "stop-epoch")); err != nil {
return fmt.Errorf("cannot read stop epoch: %w", err)
} Try / catch
ep, err := proxy.GetCreateDatabaseProxyServerEndpoint(root, opts)
if err != nil && strings.HasPrefix(err.Error(), "read proxy stop epoch under lock:") {
time.Sleep(time.Second)
ep, err = proxy.GetCreateDatabaseProxyServerEndpoint(root, opts) // transient IO often clears
} Prevention
- Serialize bd stop/start scripts
- Keep workspaces on reliable local storage
- Fix permission drift from security tooling
When it happens
Trigger: A spawn attempt is in progress (spawnAndHandoff under lock) and readStopEpoch(rootDir) returns an error — the stop-epoch file is unreadable, has bad permissions, or the storage is failing at that moment.
Common situations: Concurrent bd stop/restart mutating files in rootDir during a spawn; read-only remount triggered mid-operation (e.g. disk error flipping the FS); permission changes by security tooling; workspace on a flaky network mount.
Related errors
- discover proxy from %s under lock: %w
- probe proxy lock: %w
- %w for %s
- discover spawned proxy: %w
- re-check proxy stop epoch before publish: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d05b1bc485d53210.
Report an issue: GitHub.