{"record":{"id":"4dc4e7e981395669","repo":"gastownhall/beads","slug":"proxy-forcestopunverified-resolve-workspace-ident","errorCode":null,"errorMessage":"proxy.ForceStopUnverified: resolve workspace identity: %w","messagePattern":"proxy\\.ForceStopUnverified: resolve workspace identity: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/force_stop.go","lineNumber":179,"sourceCode":"\t\treturn nil, fmt.Errorf(\"proxy.ForceStopUnverified: read %s: %w\", report.RecordPath, err)\n\t}\n\tif record == nil {\n\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 {","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/force_stop.go#L161-L197","documentation":"ForceStopUnverified is the destructive path for legacy/unverifiable records only. This error wraps a failure to compute the workspace RootID via identity.RootID(rootDir), which is needed to prove the record is NOT a modern verifiable one. The library deliberately fails closed: it will not route a possibly-verifiable record into the destructive force path.","triggerScenarios":"Calling ForceStopUnverified when requireUnverifiableRecord calls identity.RootID(rootDir) and it errors (e.g. workspace identity file missing/corrupt, unreadable directory), so verifiability of the record cannot be established.","commonSituations":"Workspaces partially migrated between record format versions (v1 legacy vs v2 identity), identity metadata deleted or corrupted, or the rootDir passed is not the actual workspace root.","solutions":["Inspect the wrapped cause (%w); restore or regenerate the workspace identity metadata if it is missing/corrupt","Use proxy.Shutdown instead of ForceStopUnverified if the record actually has a verifiable v2 identity — the follow-on error states this explicitly","Ensure rootDir is the correct workspace root containing the identity files","If migrating versions, complete the workspace migration so identity.RootID succeeds before force-stopping"],"exampleFix":"// before\nreport, err := proxy.ForceStopUnverified(rootDir)\n// after\nif id, idErr := identity.RootID(rootDir); idErr == nil {\n    _ = id\n    err = proxy.Shutdown(rootDir) // verifiable workspace: use graceful path\n} else {\n    err = proxy.ForceStopUnverified(rootDir)\n}","handlingStrategy":"fallback","validationCode":"_, idErr := identity.RootID(rootDir)\nidentityResolvable := idErr == nil","typeGuard":null,"tryCatchPattern":"report, err := proxy.ForceStopUnverified(rootDir)\nif err != nil && strings.Contains(err.Error(), \"resolve workspace identity\") {\n    // fail-closed by design; do not force-stop blind. Investigate identity files.\n    fmt.Fprintf(os.Stderr, \"cannot verify record: %v; use graceful shutdown or fix identity\\n\", err)\n    return err\n}","preventionTips":["Complete workspace migrations before using force-stop","Never delete or hand-edit identity metadata in the database root","Use proxy.Shutdown for v2 verifiable records; reserve ForceStopUnverified for legacy ones","Confirm rootDir is the actual workspace root"],"tags":["identity","force-stop","version-migration","fail-closed"],"backgroundTag":"workspace-identity-unresolvable","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}