{"record":{"id":"f81d47d5a4eaea17","repo":"gastownhall/beads","slug":"failed-to-rename-temp-file-w","errorCode":null,"errorMessage":"failed to rename temp file: %w","messagePattern":"failed to rename temp file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/backup_export.go","lineNumber":120,"sourceCode":"\ttmpPath := tmp.Name()\n\n\tif _, err := tmp.Write(data); err != nil {\n\t\t_ = tmp.Close()\n\t\t_ = os.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"failed to write temp file: %w\", err)\n\t}\n\tif err := tmp.Sync(); err != nil {\n\t\t_ = tmp.Close()\n\t\t_ = os.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"failed to sync temp file: %w\", err)\n\t}\n\tif err := tmp.Close(); err != nil {\n\t\t_ = os.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"failed to close temp file: %w\", err)\n\t}\n\tif err := os.Rename(tmpPath, path); err != nil {\n\t\t_ = os.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"failed to rename temp file: %w\", err)\n\t}\n\treturn nil\n}\n\n// runBackupExport performs a Dolt-native backup to .beads/backup/.\n// Returns the updated state.\nfunc runBackupExport(ctx context.Context, force bool) (*backupState, error) {\n\tdir, err := backupDir()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tstate, err := loadBackupState(dir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Change detection: skip if nothing changed (unless forced)","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/backup_export.go#L102-L138","documentation":"atomicWriteFile finishes by renaming the fully-written temp file over the destination; this wraps os.Rename failure. The temp file is removed, leaving any pre-existing destination intact.","triggerScenarios":"os.Rename(tmpPath, path) fails: destination directory became unwritable/removed between create and rename, destination path changed type (e.g. backup_state.json is now a non-empty directory), or cross-filesystem rename (path relocated via symlink between mounts).","commonSituations":"Another process deleted/recreated .beads mid-run; .beads/backup_state.json exists as a directory; exotic filesystems lacking atomic rename; the symlink-target caveat noted in the file's comments (path resolving across filesystems via symlink).","solutions":["Check that .beads/backup_state.json is not a directory: if it is, remove it (rm -rf .beads/backup_state.json).","Ensure .beads still exists and is writable at rename time; avoid concurrent processes deleting it.","If .beads is a symlink, per the code's comment resolve it with filepath.EvalSymlinks semantics — keep .beads on the same filesystem as the workspace.","Retry after resolving; the temp file was cleaned up automatically."],"exampleFix":"// shell\nfile .beads/backup_state.json    # if 'directory':\nrm -rf .beads/backup_state.json && bd sync","handlingStrategy":"validation","validationCode":"const p = \".beads/backup_state.json\"\nif st, err := os.Lstat(p); err == nil && st.IsDir() {\n    os.RemoveAll(p) // rename over a non-empty dir always fails\n}\n// ensure dest stays on the same filesystem as its temp file\nif st, err := os.Stat(\".beads\"); err == nil && st.Mode()&os.ModeSymlink != 0 {\n    if resolved, err := filepath.EvalSymlinks(\".beads\"); err == nil {\n        _ = resolved // verify same-device with os.Stat + syscall same-device check\n    }\n}","typeGuard":"func renameTargetOk(path string) bool {\n    st, err := os.Lstat(path)\n    return err != nil || !st.IsDir()\n}","tryCatchPattern":"if err := saveBackupState(dir, state); err != nil {\n    if strings.Contains(err.Error(), \"rename temp file\") {\n        _ = os.RemoveAll(filepath.Join(dir, \"backup_state.json\"))\n        if retryErr := saveBackupState(dir, state); retryErr != nil {\n            return retryErr\n        }\n    } else if err != nil {\n        return err\n    }\n}","preventionTips":["Don't mutate .beads concurrently with running bd commands","Keep .beads a real directory, not a cross-filesystem symlink","Remove any accidental directory at .beads/backup_state.json"],"tags":["go","filesystem","rename","atomic-write"],"backgroundTag":"rename-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}