gastownhall/beads · error

probe proxy lock: %w

Error message

probe proxy lock: %w

What it means

This is not a lock-contention issue: util.TryLock failed with an error that is NOT 'lock already held' (lockfile.IsLocked(err) is false). That means the lock file itself could not be probed/created — an I/O or environmental failure — so the library cannot safely proceed and wraps the underlying error. Treat it as a filesystem problem, not a busy proxy.

Source

Thrown at internal/storage/dbproxy/proxy/endpoint.go:271

			}
			if markerActive {
				lock.Unlock()
				lastSpawnErr = nil
				// This break exits the switch only; the outer discovery loop
				// continues with its normal bounded poll.
				break
			}

			var ep Endpoint
			ep, lastSpawnErr = spawnAndHandoff(rootDir, opts, deadline, stopEpoch, lock, discovery)
			if lastSpawnErr == nil {
				return ep, nil
			}
			if errors.Is(lastSpawnErr, errStartInterrupted) {
				return Endpoint{}, lastSpawnErr
			}
		case !lockfile.IsLocked(err):
			return Endpoint{}, fmt.Errorf("probe proxy lock: %w", err)
		case discovery.status == adoptionLegacy:
			recordPath := pidfile.Path(rootDir, PIDFileName)
			return Endpoint{}, fmt.Errorf(
				"legacy proxy record %s is protected by held lock %s; stop the pre-upgrade proxy with the old bd binary or wait for its idle exit, then quarantine the record manually by renaming %s to %s.stale-<unix-timestamp> before retrying",
				recordPath,
				filepath.Join(rootDir, LockFileName),
				recordPath,
				recordPath,
			)
		}

		select {
		case <-timeout.C:
			if lastSpawnErr != nil {
				return Endpoint{}, lastSpawnErr
			}
			return Endpoint{}, fmt.Errorf("timeout waiting for proxy on %s", rootDir)
		case <-poll.C:

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify <rootDir> exists and is writable; recreate the directory if it was removed
  2. Check the mount is not read-only (mount | grep, or try touching a file in rootDir)
  3. If a stale proxy.lock file exists but is not actually locked, remove it and retry
  4. Re-run as a user with write access to the workspace

Example fix

// before
error: probe proxy lock: open /repo/.beads/proxy.lock: no such file or directory
// after
$ mkdir -p /repo/.beads && touch /repo/.beads/.write-test && rm /repo/.beads/.write-test
$ bd ready
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the workspace is writable before attempting proxy open
probe := filepath.Join(rootDir, ".write-probe")
if err := os.WriteFile(probe, nil, 0o600); err != nil {
    return fmt.Errorf("workspace not writable: %w", err)
}
os.Remove(probe)

Try / catch

err := proxy.GetCreateDatabaseProxyServerEndpoint(root, opts)
var lockErr *fs.PathError
if err != nil && strings.HasPrefix(err.Error(), "probe proxy lock:") && errors.As(err, &lockErr) {
    // filesystem-level lock failure: fix permissions/mount, do NOT busy-retry
    return fmt.Errorf("fix workspace fs: %w", err)
}

Prevention

When it happens

Trigger: util.TryLock on <rootDir>/proxy.lock returns a non-IsLocked error: the lock file cannot be opened/created because the directory is missing or read-only, the OS lock syscall fails, or the lock path is invalid.

Common situations: Workspace directory deleted or renamed while bd was running; read-only mounts (CI cache restores, WSL cross-filesystem mounts); TMPDIR/overlay filesystem restrictions; running two tools with incompatible lock semantics on the same path.

Related errors


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