{"record":{"id":"b53b1671b9596488","repo":"gastownhall/beads","slug":"timeout-after-s-waiting-for-bootstrap-lock-anoth","errorCode":null,"errorMessage":"timeout after %s waiting for bootstrap lock (another bootstrap may be running)","messagePattern":"timeout after (.+?) waiting for bootstrap lock \\(another bootstrap may be running\\)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/bootstrap.go","lineNumber":250,"sourceCode":"\n\t// Try to acquire lock with non-blocking flock and polling.\n\tdeadline := time.Now().Add(timeout)\n\tfor {\n\t\terr := lockfile.FlockExclusiveNonBlocking(f)\n\t\tif err == nil {\n\t\t\t// Lock acquired - update modification time for stale detection\n\t\t\treturn f, nil\n\t\t}\n\n\t\tif !lockfile.IsLocked(err) {\n\t\t\t// Unexpected error (not contention)\n\t\t\t_ = f.Close() // Best effort cleanup on error path\n\t\t\treturn nil, fmt.Errorf(\"failed to acquire bootstrap lock: %w\", err)\n\t\t}\n\n\t\tif time.Now().After(deadline) {\n\t\t\t_ = f.Close() // Best effort cleanup on error path\n\t\t\treturn nil, fmt.Errorf(\"timeout after %s waiting for bootstrap lock (another bootstrap may be running)\", timeout)\n\t\t}\n\n\t\t// Wait briefly before retrying\n\t\ttime.Sleep(100 * time.Millisecond)\n\t}\n}\n\n// releaseBootstrapLock releases the bootstrap lock and removes the lock file\nfunc releaseBootstrapLock(f *os.File, lockPath string) {\n\tif f != nil {\n\t\t_ = lockfile.FlockUnlock(f) // Best effort: unlock may fail if fd is bad\n\t\t_ = f.Close()               // Best effort cleanup\n\t}\n\t// Clean up lock file\n\t_ = os.Remove(lockPath) // Best effort cleanup of lock file\n}\n","sourceCodeStart":232,"sourceCodeEnd":267,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/bootstrap.go#L232-L267","documentation":"The bootstrap lock is held by another process. acquireBootstrapLock polls with non-blocking flock every 100ms until the timeout deadline passes; if the lock is never released within that window, it gives up with this timeout error, closing its own file handle first. It indicates a concurrent bootstrap is running (or a stale holder).","triggerScenarios":"Two `bd bootstrap` invocations run concurrently on the same database (e.g. two agent sessions, a CI job overlapping local work), or a previous bootstrap process crashed/hung while still holding the flock on the lock file until the deadline expires.","commonSituations":"Parallel agent workflows each calling `bd bootstrap`; a long-running `bd` process (server mode) holding the lock; a stuck dolt subprocess from an earlier failed bootstrap.","solutions":["Wait for the other bootstrap to finish, then retry — the timeout message tells you another bootstrap may be running","Find and stop the process holding the lock: `lsof .beads/bootstrap.lock` (or equivalent) and kill stale `bd`/`dolt` processes","Increase spacing between concurrent agent sessions, or serialize bootstrap calls behind your own coordination","If the holder is dead but the flock persists (unusual), delete the lock file and retry"],"exampleFix":"// before\nbd bootstrap & bd bootstrap &  # second one times out\n// after\nbd bootstrap && bd doctor  # serialize; or wait for first to exit before retrying","handlingStrategy":"retry","validationCode":"// detect a concurrent bootstrap before starting one\n// Unix: fuser .beads/bootstrap.lock 2>/dev/null && echo 'bootstrap in progress'\n// or check for running processes: pgrep -f 'bd bootstrap'","typeGuard":null,"tryCatchPattern":"if err := bd.BootstrapFromRemoteWithDB(ctx, url, target); err != nil {\n    if strings.Contains(err.Error(), \"timeout after\") {\n        // wait/poll for the other bootstrap to finish, then retry;\n        // if no holder exists, remove stale lock and retry\n    }\n}","preventionTips":["Serialize bootstrap calls across agent sessions/CI with your own coordination","Check for running `bd`/`dolt` processes before starting bootstrap","Use lsof/fuser to identify stale lock holders after crashed runs","Avoid launching parallel bd bootstrap commands on the same database"],"tags":["lock","concurrency","timeout","bootstrap"],"backgroundTag":"lock-contention-timeout","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}