{"record":{"id":"47a86df330d0b27e","repo":"gastownhall/beads","slug":"rename-s-to-s-w","errorCode":null,"errorMessage":"rename %s to %s: %w","messagePattern":"rename (.+?) to (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/endpoint.go","lineNumber":705,"sourceCode":"\ttarget, err := quarantineRecord(rootDir, PIDFileName, time.Now())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"quarantine proxy record: %w\", err)\n\t}\n\tlog.Printf(\"dbproxy: preserved proxy record as %s\", target)\n\treturn nil\n}\n\nfunc quarantineRecord(rootDir, name string, now time.Time) (string, error) {\n\tsource := pidfile.Path(rootDir, name)\n\tfor stamp := now.Unix(); ; stamp++ {\n\t\ttarget := filepath.Join(rootDir, name+\".stale-\"+strconv.FormatInt(stamp, 10))\n\t\tif _, err := os.Lstat(target); err == nil {\n\t\t\tcontinue\n\t\t} else if !errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn \"\", fmt.Errorf(\"inspect quarantine target %s: %w\", target, err)\n\t\t}\n\t\tif err := os.Rename(source, target); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"rename %s to %s: %w\", source, target, err)\n\t\t}\n\t\treturn target, nil\n\t}\n}\n\nfunc sweepOldQuarantines(rootDir string, now time.Time) error {\n\tentries, err := os.ReadDir(rootDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcutoff := now.Add(-quarantineRetention).Unix()\n\tprefixes := []string{\n\t\tPIDFileName + \".stale-\",\n\t\tserver.PIDFileName + \".stale-\",\n\t}\n\tvar errs []error\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/endpoint.go#L687-L723","documentation":"quarantineRecord renames the source pidfile to the chosen <name>.stale-<unix-ts> target; this error wraps an os.Rename failure. The old proxy record is preserved but not moved, so the caller (spawn path) aborts the restart.","triggerScenarios":"os.Rename(source, target) fails after Lstat reported the target as non-existent — typical causes: target created by a racing process in the gap, source file removed concurrently, permission denied, or cross-device link if rootDir spans mounts.","commonSituations":"Two bd processes quarantining simultaneously; antivirus locking the pidfile on Windows (ACCESS_DENIED); pidfile deleted by a concurrent shutdown between Lstat and Rename; workspace on a network mount with flaky rename semantics.","solutions":["Re-run the command — quarantineRecord retries with incremented timestamps on subsequent attempts","Check permissions/locks on both source pidfile and workspace root; exclude workspace from AV real-time scanning","Confirm rootDir is a single filesystem (no symlink/mount trickery causing EXDEV)","Check the wrapped errno via errors.Unwrap for the specific OS error and fix accordingly"],"exampleFix":"// before\nif err := os.Rename(source, target); err != nil {\n    return \"\", fmt.Errorf(\"rename %s to %s: %w\", source, target, err)\n}\n// after\nif err := os.Rename(source, target); err != nil {\n    if errors.Is(err, fs.ErrNotExist) { // source vanished: racing shutdown won\n        return \"\", nil // nothing to quarantine\n    }\n    return \"\", fmt.Errorf(\"rename %s to %s: %w\", source, target, err)\n}","handlingStrategy":"retry","validationCode":"src := pidfile.Path(root, PIDFileName)\nif _, err := os.Stat(src); err != nil {\n    return fmt.Errorf(\"pidfile gone before quarantine: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n    target, err := quarantineRecord(root, PIDFileName, time.Now())\n    if err == nil { break }\n    if errors.Is(err, fs.ErrPermission) || errors.Is(err, syscall.EXDEV) { return err } // non-retryable\n    time.Sleep(time.Duration(attempt+1) * 50 * time.Millisecond)\n}","preventionTips":["Run one bd process per workspace at a time to avoid quarantine rename races","Add workspace exclusions to Windows AV that locks files during rename","Keep the workspace on a local filesystem supporting atomic rename","Check wrapped errno (EACCES/EXDEV/ENOENT) to distinguish fixable permission issues from races"],"tags":["filesystem","rename","race-condition"],"backgroundTag":"file-rename-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}