gastownhall/beads · error
resolve workspace identity: %w
Error message
resolve workspace identity: %w
What it means
This error wraps a failure from identity.RootID() while validating a pidfile kill-record during proxy shutdown. The proxy records the workspace root identity (derived from the root directory) in its pidfile and re-checks it before force-stopping a stale daemon. If the workspace root ID cannot be resolved (e.g. the directory is unreadable or has no stable identity), validation aborts with this wrapped error rather than killing a process with unknown ownership.
Source
Thrown at internal/storage/dbproxy/proxy/shutdown.go:377
time.Sleep(shutdownConfirmPoll)
}
}
func validateKillRecord(
rootDir string,
pf *pidfile.PidFile,
wantKind string,
checks killRecordChecks,
) error {
if err := pf.ValidateV2(wantKind); err != nil {
return err
}
if !checks.VerifyRoot {
return nil
}
rootID, err := identity.RootID(rootDir)
if err != nil {
return fmt.Errorf("resolve workspace identity: %w", err)
}
if pf.RootID != rootID {
return fmt.Errorf("root identity mismatch (record has %q, workspace has %q)", pf.RootID, rootID)
}
return nil
}
func classifyInvalidKillRecord(pf *pidfile.PidFile, validationErr error) (dead bool, live bool, err error) {
if !isPIDFileValidationError(validationErr) {
return false, false, nil
}
return probeUnverifiablePID(pf.Pid)
}
func isPIDFileValidationError(err error) bool {
return errors.Is(err, pidfile.ErrLegacySchema) ||
errors.Is(err, pidfile.ErrBadPid) ||
errors.Is(err, pidfile.ErrBadPort) ||View on GitHub (pinned to 71377f2769)
Solutions
- Re-create the workspace metadata so identity.RootID can resolve the root directory (run bd doctor or reinitialize the project in place).
- Verify the root directory exists, is readable by the current user, and was not renamed since the daemon started.
- Stop any stale daemon by hand (kill the recorded PID) and remove the stale pidfile, then restart.
- Check file permissions on the workspace root (ls -ld) and re-run with correct ownership.
Example fix
// before: root dir moved, pidfile references old identity $ bd doctor // after: restore/reinit workspace then retry $ cd /correct/workspace && bd doctor && bd ...
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(rootDir); err != nil {
return fmt.Errorf("workspace root unreadable before proxy stop: %w", err)
}
if _, err := identity.RootID(rootDir); err != nil {
// resolve identity up front so validateKillRecord cannot fail
return err
} Try / catch
if _, err := stopAndAcquire(ctx); err != nil {
if errors.Is(err, errIdentityUnresolvable) || strings.Contains(err.Error(), "resolve workspace identity") {
// fall back to manual pidfile cleanup
}
} Prevention
- Do not rename or move a workspace directory while a bd daemon is running.
- Keep the workspace root readable by every user/account that runs bd commands.
- Do not delete workspace metadata directories (.beads) while daemons hold pidfiles.
- Run bd doctor periodically to catch identity/pidfile drift early.
When it happens
Trigger: stopAndAcquire -> validateKillRecord calls identity.RootID(rootDir), which returns an error (unreadable root dir, missing temp/lock artifacts the identity derivation depends on, permission issues).
Common situations: Running `bd` in a directory that was moved/renamed after the daemon started; running with insufficient permissions on the workspace root; deleting parts of the workspace (e.g. .beads metadata) that identity.RootID uses to derive a stable ID.
Related errors
- read backend record %s: %w
- quarantine dead unverifiable backend record: %w
- resolve backend root identity: %w
- root identity mismatch (record has %q, workspace has %q)
- quarantine orphan backend record: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c1ee576b3350addb.
Report an issue: GitHub.