{"record":{"id":"92cc47a57f1b4fa0","repo":"gastownhall/beads","slug":"proxy-forcestopunverified-probe-s-w","errorCode":null,"errorMessage":"proxy.ForceStopUnverified: probe %s: %w","messagePattern":"proxy\\.ForceStopUnverified: probe (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/force_stop.go","lineNumber":106,"sourceCode":"// forceStopRecord runs the inspect-signal-quarantine procedure for one\n// process record, writing partial progress into report as it goes.\nfunc forceStopRecord(\n\trootDir string,\n\tlockName string,\n\tpidName string,\n\twantKind string,\n\ttimeout time.Duration,\n\treport *ForceStopReport,\n) error {\n\tdeadline := time.Now().Add(timeout)\n\tlockPath := filepath.Join(rootDir, lockName)\n\tlock, err := util.TryLock(lockPath)\n\tif err == nil {\n\t\tdefer lock.Unlock()\n\t\treturn forceStopRecordLocked(rootDir, pidName, wantKind, deadline, report)\n\t}\n\tif !lockfile.IsLocked(err) {\n\t\treturn fmt.Errorf(\"proxy.ForceStopUnverified: probe %s: %w\", lockPath, err)\n\t}\n\treport.LockWasHeld = true\n\n\trecord, err := readForceStopRecord(rootDir, pidName, report)\n\tif err != nil || record == nil {\n\t\treturn err\n\t}\n\tif err := requireUnverifiableRecord(rootDir, record, wantKind); err != nil {\n\t\treturn err\n\t}\n\tif err := inspectAndStopUnverifiedPID(rootDir, record.Pid, deadline, report); err != nil {\n\t\treturn err\n\t}\n\n\tlock, err = acquireForceStopLock(lockPath, deadline)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/force_stop.go#L88-L124","documentation":"forceStopRecord attempts a non-blocking TryLock on the proxy lock file; if the lock attempt fails with an error other than 'already locked', this error wraps it. The library distinguishes 'lock held by someone' (proceeds to the held-lock force path) from 'lock mechanism itself failed' (this error), since the latter means it cannot safely probe the record.","triggerScenarios":"Calling ForceStopUnverified (via forceStopRecord) when util.TryLock(lockPath) fails with an unexpected error — e.g. the lock file cannot be created/opened due to permissions, the path is a directory, or an I/O error occurs.","commonSituations":"Lock file path owned by another user, a corrupted lock file, or a workspace directory with restrictive permissions after a backup restore.","solutions":["Check the wrapped cause (%w) for the underlying open/lock syscall error and fix permissions on the lock file and its directory","Remove a corrupted or wrongly-typed lock file when no live proxy owns it (verify with ps first)","Ensure lockPath points at the intended workspace root, not a stale/moved path","Retry once the filesystem is healthy; transient EIO on network filesystems resolves after remount"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"func lockFileOpenable(path string) error {\n    f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0o644)\n    if err != nil {\n        return err\n    }\n    return f.Close()\n}","typeGuard":null,"tryCatchPattern":"report, err := proxy.ForceStopUnverified(rootDir)\nif err != nil && strings.Contains(err.Error(), \"probe \") {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        fmt.Fprintf(os.Stderr, \"lock file %s: %v\\n\", perr.Path, perr.Err)\n    }\n    return err\n}","preventionTips":["Keep lock files and their directories writable by the bd user","Do not manually delete lock files while proxies may be running","Check path correctness after moving workspaces","Treat EIO on network filesystems as transient and retry"],"tags":["lockfile","filesystem","force-stop","permissions"],"backgroundTag":"lock-acquisition-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}