{"record":{"id":"53de1e850e660dbe","repo":"gastownhall/beads","slug":"root-identity-mismatch-record-has-q-workspace-h-53de1e","errorCode":null,"errorMessage":"root identity mismatch (record has %q, workspace has %q)","messagePattern":"root identity mismatch \\(record has %q, workspace has %q\\)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/shutdown.go","lineNumber":380,"sourceCode":"\nfunc validateKillRecord(\n\trootDir string,\n\tpf *pidfile.PidFile,\n\twantKind string,\n\tchecks killRecordChecks,\n) error {\n\tif err := pf.ValidateV2(wantKind); err != nil {\n\t\treturn err\n\t}\n\tif !checks.VerifyRoot {\n\t\treturn nil\n\t}\n\trootID, err := identity.RootID(rootDir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"resolve workspace identity: %w\", err)\n\t}\n\tif pf.RootID != rootID {\n\t\treturn fmt.Errorf(\"root identity mismatch (record has %q, workspace has %q)\", pf.RootID, rootID)\n\t}\n\treturn nil\n}\n\nfunc classifyInvalidKillRecord(pf *pidfile.PidFile, validationErr error) (dead bool, live bool, err error) {\n\tif !isPIDFileValidationError(validationErr) {\n\t\treturn false, false, nil\n\t}\n\treturn probeUnverifiablePID(pf.Pid)\n}\n\nfunc isPIDFileValidationError(err error) bool {\n\treturn errors.Is(err, pidfile.ErrLegacySchema) ||\n\t\terrors.Is(err, pidfile.ErrBadPid) ||\n\t\terrors.Is(err, pidfile.ErrBadPort) ||\n\t\terrors.Is(err, pidfile.ErrKindMismatch) ||\n\t\terrors.Is(err, pidfile.ErrMissingBirth)\n}","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/shutdown.go#L362-L398","documentation":"A hard mismatch check during pidfile kill-record validation: the daemon recorded a workspace RootID that no longer matches the RootID computed for the current root directory. The proxy refuses to kill the recorded process because it may belong to a different workspace, preventing cross-workspace process kills.","triggerScenarios":"stopAndAcquire -> validateKillRecord compares pf.RootID (stored in the pidfile) against identity.RootID(rootDir); any inequality raises this error — typically after the workspace directory was moved, copied, or the root was recreated.","commonSituations":"Cloning/moving a project directory while a daemon from the original location is still running; running two workspaces that share an inherited pidfile path; restoring the repo from a backup that changed identity metadata.","solutions":["Kill the stale daemon manually (from the pidfile PID) and delete the pidfile so a fresh one with the current RootID is written.","Confirm you are in the same physical directory the daemon was started in; cd back to the original workspace path.","Recreate the workspace metadata (bd doctor / reinitialize) so identity.RootID matches what the daemon recorded.","Copy the original workspace back to its original path if it was moved."],"exampleFix":"// before: stale pidfile with mismatched RootID\nkill $(cat .beads/bd.pid); rm .beads/bd.pid\n// after: restart in correct workspace\nbd ... # new pidfile written with current RootID","handlingStrategy":"validation","validationCode":"pf, err := pidfile.Read(path)\nif err != nil { return err }\nrootID, err := identity.RootID(rootDir)\nif err != nil { return err }\nif pf.RootID != rootID {\n    // stale record from another workspace: clean up manually, never kill\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := stopAndAcquire(ctx); err != nil {\n    if strings.Contains(err.Error(), \"root identity mismatch\") {\n        // treat pidfile as stale: remove it manually instead of killing the PID\n    }\n}","preventionTips":["Always run bd from the same directory the daemon was started in.","Avoid cloning/copying a workspace that contains a live pidfile; remove .beads pidfiles before copying.","One daemon per workspace path — do not share workspace directories across machines or containers.","After moving a project, stop the daemon first, then move, then restart."],"tags":["go","workspace-identity","pidfile","safety-check"],"backgroundTag":"workspace-identity-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}