{"record":{"id":"1dc6ac3272226035","repo":"gastownhall/beads","slug":"remove-dead-spawn-marker-w","errorCode":null,"errorMessage":"remove dead spawn marker: %w","messagePattern":"remove dead spawn marker: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/endpoint.go","lineNumber":1044,"sourceCode":"}\n\nfunc inspectSpawnMarkerLocked(rootDir string) (bool, error) {\n\tmarker, err := readSpawnMarker(rootDir)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"inspect proxy spawn marker: %w\", err)\n\t}\n\tif marker == nil {\n\t\treturn false, nil\n\t}\n\tmatched, err := procid.Verify(marker.PID, procid.Token(marker.Birth))\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"verify proxy spawn owner pid %d: %w\", marker.PID, err)\n\t}\n\tif matched {\n\t\treturn true, nil\n\t}\n\tif err := os.Remove(filepath.Join(rootDir, spawnMarkerFileName)); err != nil && !errors.Is(err, fs.ErrNotExist) {\n\t\treturn false, fmt.Errorf(\"remove dead spawn marker: %w\", err)\n\t}\n\treturn false, nil\n}\n\nfunc clearSpawnMarkerAfterLock(rootDir string) error {\n\terr := os.Remove(filepath.Join(rootDir, spawnMarkerFileName))\n\tif err != nil && !errors.Is(err, fs.ErrNotExist) {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc clearOwnSpawnMarker(rootDir string, own spawnMarker) error {\n\tdeadline := time.Now().Add(shutdownConfirmDeadline)\n\tfor {\n\t\tmarker, err := readSpawnMarker(rootDir)\n\t\tif err != nil || marker == nil {\n\t\t\treturn err","sourceCodeStart":1026,"sourceCodeEnd":1062,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/endpoint.go#L1026-L1062","documentation":"This error wraps a failure to remove a spawn marker file that belongs to a process already confirmed dead. The library throws it because a dead marker left on disk would keep triggering spurious spawn-owner checks; if removal fails for a reason other than the file not existing, the failure is surfaced instead of silently ignored.","triggerScenarios":"After procid.Verify reports the recorded PID is not running, calling os.Remove on <rootDir>/<spawnMarkerFileName> fails with an error that is not fs.ErrNotExist — e.g. EACCES/EPERM on the directory or file, or the path is a directory rather than a file.","commonSituations":"Read-only or root-owned database directory after restoring a backup with wrong ownership, stale markers under a directory owned by a different user/container UID mismatch, or a directory named like the marker file blocking removal.","solutions":["Fix permissions on the database root directory so the current user can delete files in it (chown/chmod)","Remove the marker file manually: rm <dbdir>/.bd-spawn-marker (actual spawnMarkerFileName)","Check the wrapped cause (%w); if the marker path is a directory, remove the directory instead","If the marker is already gone, the matching errors.Is(err, fs.ErrNotExist) branch means no action is needed — rerun the operation"],"exampleFix":"// before\nif err := os.Remove(filepath.Join(rootDir, spawnMarkerFileName)); err != nil && !errors.Is(err, fs.ErrNotExist) {\n    return false, fmt.Errorf(\"remove dead spawn marker: %w\", err)\n}\n// after\nmarkerPath := filepath.Join(rootDir, spawnMarkerFileName)\nif err := os.Remove(markerPath); err != nil && !errors.Is(err, fs.ErrNotExist) {\n    _ = os.Chmod(rootDir, 0o755)\n    if err2 := os.Remove(markerPath); err2 != nil && !errors.Is(err2, fs.ErrNotExist) {\n        return false, fmt.Errorf(\"remove dead spawn marker: %w\", err2)\n    }\n}","handlingStrategy":"try-catch","validationCode":"func canRemoveMarker(rootDir string) error {\n    info, err := os.Stat(rootDir)\n    if err != nil {\n        return err\n    }\n    if !info.IsDir() {\n        return fmt.Errorf(\"%s is not a directory\", rootDir)\n    }\n    f, err := os.CreateTemp(rootDir, \".wtest\")\n    if err != nil {\n        return err\n    }\n    _ = f.Close()\n    return os.Remove(f.Name())\n}","typeGuard":null,"tryCatchPattern":"if err := verifySpawnOwner(rootDir); err != nil {\n    if strings.Contains(err.Error(), \"remove dead spawn marker\") {\n        fmt.Fprintf(os.Stderr, \"fix permissions on %s, then retry: %v\\n\", rootDir, err)\n    }\n}","preventionTips":["Keep database directories owned by the same user that runs bd","Avoid read-only mounts for active workspaces","Restore backups with correct ownership (chown -R)","Never replace the marker file with a directory"],"tags":["filesystem","permissions","spawn-marker","cleanup"],"backgroundTag":"file-permission-denied","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}