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

  1. Delete the stale spawn marker file (<dbdir>/<spawnMarkerFileName>) and retry, since the marker is advisory cleanup state
  2. Inspect the marker contents; if the PID or birth token is malformed, remove the file rather than re-running verification
  3. 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
  4. 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

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


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