{"record":{"id":"337dc66f9a74c7c9","repo":"gastownhall/beads","slug":"timeout-clearing-spawn-marker-s","errorCode":null,"errorMessage":"timeout clearing spawn marker %s","messagePattern":"timeout clearing spawn marker (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/endpoint.go","lineNumber":1081,"sourceCode":"\t\t}\n\t\tif *marker != own {\n\t\t\treturn nil\n\t\t}\n\n\t\tlock, err := util.TryLock(filepath.Join(rootDir, LockFileName))\n\t\tif err == nil {\n\t\t\tcurrent, readErr := readSpawnMarker(rootDir)\n\t\t\tif readErr == nil && current != nil && *current == own {\n\t\t\t\treadErr = clearSpawnMarkerAfterLock(rootDir)\n\t\t\t}\n\t\t\tlock.Unlock()\n\t\t\treturn readErr\n\t\t}\n\t\tif !lockfile.IsLocked(err) {\n\t\t\treturn err\n\t\t}\n\t\tif time.Now().After(deadline) {\n\t\t\treturn fmt.Errorf(\"timeout clearing spawn marker %s\", filepath.Join(rootDir, spawnMarkerFileName))\n\t\t}\n\t\ttime.Sleep(shutdownConfirmPoll)\n\t}\n}\n","sourceCodeStart":1063,"sourceCodeEnd":1086,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/endpoint.go#L1063-L1086","documentation":"This error indicates the spawn-marker clearing loop kept hitting a locked lockfile past its deadline, so clearing the marker timed out. The library throws it to prevent waiting forever on a spawn marker that some other process holds locked, typically when a prior proxy process is still shutting down or is stuck.","triggerScenarios":"Calling clearSpawnMarkerAfterLock (or the polling path at endpoint.go:1081) while another process holds an flock/lockfile on the spawn marker, and the lock is not released before the deadline computed from shutdownConfirmDeadline.","commonSituations":"A proxy process hung mid-shutdown holding the marker lock, a killed process whose lock lingers momentarily, or heavy contention when many bd invocations race to stop/verify proxies in the same workspace.","solutions":["Wait and retry once other proxy processes have exited (check with ps/lsof which process holds the lock)","Identify and kill the stale holder: use lsof on the marker file to find the locking PID and terminate it if it is defunct","Remove the marker file manually when no live proxy owns it, then re-run the command","Increase the allowed deadline if shutdown legitimately takes long on this machine"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"func markerLockFree(rootDir string) bool {\n    f, err := os.OpenFile(filepath.Join(rootDir, \"spawn.marker\"), os.O_RDWR, 0o644)\n    if err != nil {\n        return os.IsNotExist(err)\n    }\n    defer f.Close()\n    return syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) == nil\n}","typeGuard":null,"tryCatchPattern":"err := clearSpawnMarkerAfterLock(rootDir)\nif err != nil && strings.Contains(err.Error(), \"timeout clearing spawn marker\") {\n    // find and wait for the lock holder, then retry once\n    time.Sleep(2 * time.Second)\n    err = clearSpawnMarkerAfterLock(rootDir)\n}","preventionTips":["Ensure proxy processes handle SIGTERM and release locks promptly","Avoid running many concurrent bd stop/verify operations on one workspace","Use lsof to check lock holders before force-clearing","Increase shutdown deadline on slow machines"],"tags":["lockfile","timeout","concurrency","spawn-marker"],"backgroundTag":"lock-contention-timeout","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}