gastownhall/beads · error
verify proxy spawn owner pid %d: %w
Error message
verify proxy spawn owner pid %d: %w
What it means
This error wraps a failure from procid.Verify when checking whether the PID recorded in a proxy spawn marker file still belongs to a live process with the recorded birth token. The library throws it when the spawn-owner liveness check cannot be performed (e.g. the process table cannot be consulted or the recorded PID is malformed), so the caller cannot safely conclude whether a stale proxy marker is owned by a running process.
Source
Thrown at internal/storage/dbproxy/proxy/endpoint.go:1038
return nil, fmt.Errorf("decode %s: %w", path, err)
}
if marker.Schema != 1 || marker.PID <= 0 || marker.Birth == "" {
return nil, fmt.Errorf("invalid spawn marker %s", path)
}
return &marker, nil
}
func inspectSpawnMarkerLocked(rootDir string) (bool, error) {
marker, err := readSpawnMarker(rootDir)
if err != nil {
return false, fmt.Errorf("inspect proxy spawn marker: %w", err)
}
if marker == nil {
return false, nil
}
matched, err := procid.Verify(marker.PID, procid.Token(marker.Birth))
if err != nil {
return false, fmt.Errorf("verify proxy spawn owner pid %d: %w", marker.PID, err)
}
if matched {
return true, nil
}
if err := os.Remove(filepath.Join(rootDir, spawnMarkerFileName)); err != nil && !errors.Is(err, fs.ErrNotExist) {
return false, fmt.Errorf("remove dead spawn marker: %w", err)
}
return false, nil
}
func clearSpawnMarkerAfterLock(rootDir string) error {
err := os.Remove(filepath.Join(rootDir, spawnMarkerFileName))
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Delete the stale spawn marker file (<dbdir>/<spawnMarkerFileName>) and retry, since the marker is advisory cleanup state
- Inspect the marker contents; if the PID or birth token is malformed, remove the file rather than re-running verification
- Check the wrapped cause (%w) — if it is an OS-level process-lookup failure, verify the process filesystem (e.g. /proc) is mounted and readable
- Ensure no external tooling rewrites PID files with padded or non-numeric values
Example fix
// before
matched, err := procid.Verify(marker.PID, procid.Token(marker.Birth))
// after
if marker.PID <= 0 {
_ = os.Remove(filepath.Join(rootDir, spawnMarkerFileName))
return false, nil
}
matched, err := procid.Verify(marker.PID, procid.Token(marker.Birth)) Defensive patterns
Strategy: validation
Validate before calling
func markerLooksValid(rootDir string) bool {
data, err := os.ReadFile(filepath.Join(rootDir, "spawn.marker"))
if err != nil || len(bytes.TrimSpace(data)) == 0 {
return false
}
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
return err == nil && pid > 0
} Type guard
func isSpawnOwnerVerifyError(err error) bool {
return err != nil && strings.Contains(err.Error(), "verify proxy spawn owner pid")
} Try / catch
if err := verifySpawnOwner(rootDir); err != nil {
var target *fs.PathError
if errors.As(err, &target) {
// OS-level lookup failure: inspect cause before deciding
_ = target
}
// Safe fallback: treat marker as stale and remove it
_ = os.Remove(filepath.Join(rootDir, "spawn.marker"))
} Prevention
- Never hand-edit spawn marker files
- Validate PID files are numeric and positive before relying on them
- Ensure /proc (or equivalent) is mounted in containers
- Clean stale markers after unclean shutdowns
When it happens
Trigger: Calling the spawn-marker verification path in internal/storage/dbproxy/proxy/endpoint.go when a spawn marker file exists but procid.Verify(marker.PID, procid.Token(marker.Birth)) returns an error — typically a corrupted marker containing a non-numeric/invalid PID, or an OS failure reading process info for the recorded PID.
Common situations: A leftover spawn marker in the database directory after a crash, a marker file manually edited or truncated, or a container/OS environment where /proc lookups fail (restricted procfs, chroot, seccomp filters blocking process queries).
Related errors
- pidfile: invalid pid
- writing PID file: %w
- discover proxy from %s: %w
- quarantine proxy record: %w
- read backend record %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/11279a15e26178e9.
Report an issue: GitHub.