{"record":{"id":"965b838f25729ca9","repo":"gastownhall/beads","slug":"remove-expired-quarantine-s-w","errorCode":null,"errorMessage":"remove expired quarantine %s: %w","messagePattern":"remove expired quarantine (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/dbproxy/proxy/endpoint.go","lineNumber":741,"sourceCode":"\t\tif entry.IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tvar stampText string\n\t\tfor _, prefix := range prefixes {\n\t\t\tif strings.HasPrefix(entry.Name(), prefix) {\n\t\t\t\tstampText = strings.TrimPrefix(entry.Name(), prefix)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif stampText == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tstamp, err := strconv.ParseInt(stampText, 10, 64)\n\t\tif err != nil || stamp >= cutoff {\n\t\t\tcontinue\n\t\t}\n\t\tif err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) {\n\t\t\terrs = append(errs, fmt.Errorf(\"remove expired quarantine %s: %w\", entry.Name(), err))\n\t\t}\n\t}\n\treturn errors.Join(errs...)\n}\n\nfunc cleanupOrphanBackend(rootDir string) error {\n\trecordPath := pidfile.Path(rootDir, server.PIDFileName)\n\tpf, readErr := pidfile.Read(rootDir, server.PIDFileName)\n\n\tchildLockPath := filepath.Join(rootDir, server.LockFileName)\n\tchildLock, lockErr := util.TryLock(childLockPath)\n\tswitch {\n\tcase lockErr == nil:\n\t\tchildLock.Unlock()\n\tcase lockfile.IsLocked(lockErr):\n\t\tpid := 0\n\t\tif pf != nil {\n\t\t\tpid = pf.Pid","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/endpoint.go#L723-L759","documentation":"sweepOldQuarantines removes .stale-<stamp> pidfile records older than quarantineRetention; this error wraps os.Remove failures for expired entries. Errors are accumulated and joined, so one bad file does not stop the sweep, but any failure surfaces here.","triggerScenarios":"os.Remove on an expired quarantine file fails with a non-ErrNotExist error during spawnAndHandoff's retention sweep — typically permission denied or the file being held open by another process.","commonSituations":"Stale quarantine files owned by a different user (root-created records, then running bd as a normal user); AV/indexer holding the old file open on Windows; read-only remount of the workspace.","solutions":["Fix ownership/permissions of the stale files: chown/chmod the workspace or remove them manually (rm <root>/*.stale-*)","Re-run as the user that owns the stale records, or align user namespaces in containers","On Windows, close tools/AV holding the file or add the workspace to exclusions","Ignore if benign — the sweep error is non-fatal to spawning and the expired files can be cleaned manually"],"exampleFix":"// before\nif err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) {\n    errs = append(errs, fmt.Errorf(\"remove expired quarantine %s: %w\", entry.Name(), err))\n}\n// after\nif err := os.Remove(filepath.Join(rootDir, entry.Name())); err != nil && !errors.Is(err, fs.ErrNotExist) && !errors.Is(err, fs.ErrPermission) {\n    errs = append(errs, fmt.Errorf(\"remove expired quarantine %s: %w\", entry.Name(), err))\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := sweepOldQuarantines(root, time.Now()); err != nil {\n    // joined errors: log and continue; spawn is still valid without the sweep\n    log.Printf(\"quarantine sweep skipped: %v\", err)\n}","preventionTips":["Run all bd usage of a workspace under one OS user so cleanup can remove old records","Add the workspace to AV exclusions to prevent open-handle blocks on Windows","Manually clear *.stale-* files from long-lived workspaces during maintenance","Don't remount the workspace read-only while bd sessions are active"],"tags":["filesystem","cleanup","permissions"],"backgroundTag":"file-delete-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}