{"record":{"id":"ec25e56215f15059","repo":"gastownhall/beads","slug":"proxy-forcestopunverified-record-has-a-verifiable","errorCode":null,"errorMessage":"proxy.ForceStopUnverified: record has a verifiable v2 workspace identity; use proxy.Shutdown","messagePattern":"proxy\\.ForceStopUnverified: record has a verifiable v2 workspace identity; use proxy\\.Shutdown","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/force_stop.go","lineNumber":182,"sourceCode":"\t\treturn nil, nil\n\t}\n\treport.RecordFound = true\n\treport.PID = record.Pid\n\treturn record, nil\n}\n\nfunc requireUnverifiableRecord(rootDir string, record *pidfile.PidFile, wantKind string) error {\n\tif err := record.ValidateV2(wantKind); err != nil {\n\t\treturn nil\n\t}\n\trootID, err := identity.RootID(rootDir)\n\tif err != nil {\n\t\t// Failing open here would route a possibly-verifiable record into the\n\t\t// destructive force path; surface the identity failure instead.\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: resolve workspace identity: %w\", err)\n\t}\n\tif record.RootID == rootID {\n\t\treturn errors.New(\n\t\t\t\"proxy.ForceStopUnverified: record has a verifiable v2 workspace identity; use proxy.Shutdown\",\n\t\t)\n\t}\n\treturn nil\n}\n\nfunc inspectAndStopUnverifiedPID(rootDir string, pid int, deadline time.Time, report *ForceStopReport) error {\n\tif pid <= 0 {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: record %s has invalid pid %d\", report.RecordPath, pid)\n\t}\n\t// One stable handle covers inspection and signaling, so the PID cannot be\n\t// recycled between the executable check and the kill on platforms with a\n\t// pinning primitive (Linux pidfd, Windows process handle).\n\tproc, gone, err := openUnverifiedProcess(pid)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: open pid %d: %w\", pid, err)\n\t}\n\tif gone {","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/force_stop.go#L164-L200","documentation":"requireUnverifiableRecord refuses to force-stop a pidfile record whose RootID matches the current workspace. Such a record has a verifiable v2 workspace identity, meaning the safe proxy.Shutdown path should be used instead of the destructive force-stop path. ForceStopUnverified is deliberately restricted to records whose ownership cannot be verified.","triggerScenarios":"Calling proxy.ForceStopUnverified on a rootDir whose pidfile record was written by the current workspace (record.RootID == resolved rootID).","commonSituations":"Misunderstanding the API split: using ForceStopUnverified for normal restarts instead of Shutdown; workspace identity files regenerated or moved so RootID unexpectedly matches.","solutions":["Call proxy.Shutdown instead of ForceStopUnverified for records with a verifiable identity","Verify you are targeting the correct rootDir (the error means this workspace owns the record)","If the record is truly stale, remove the identity mismatch or delete the pidfile manually after confirming the process"],"exampleFix":"// before\n_, err := proxy.ForceStopUnverified(root) // record owned by this workspace\n// after\nreport, err := proxy.Shutdown(ctx, root) // safe, verified path","handlingStrategy":"try-catch","validationCode":"if record.RootID == currentWorkspaceRootID() {\n    // record is verifiable — use Shutdown, not ForceStopUnverified\n    return proxy.Shutdown(ctx, root)\n}","typeGuard":null,"tryCatchPattern":"if _, err := proxy.ForceStopUnverified(root); err != nil {\n    if strings.Contains(err.Error(), \"verifiable v2 workspace identity\") {\n        _, err = proxy.Shutdown(ctx, root)\n    }\n    return err\n}","preventionTips":["Use ForceStopUnverified only for records from other/unknown workspaces","Default to proxy.Shutdown for your own workspace's pidfile","Compare record.RootID against the local rootID before choosing the force path"],"tags":["go","force-stop","api-misuse"],"backgroundTag":"wrong-api-for-record","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}