{"record":{"id":"6e0fccc4ef76ce20","repo":"gastownhall/beads","slug":"failed-to-write-temp-file-w","errorCode":null,"errorMessage":"failed to write temp file: %w","messagePattern":"failed to write temp file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/backup_export.go","lineNumber":107,"sourceCode":"//     entry; a crash between the rename and a subsequent directory fsync\n//     can still lose the rename itself on some filesystems.\n//   - os.Rename's atomic-replace guarantee is a POSIX/Unix property; it is\n//     not guaranteed on Windows. It also does not follow a symlink at\n//     path — it replaces whatever is there, symlink or not — so a caller\n//     that must preserve a symlink's target should resolve path with\n//     filepath.EvalSymlinks first (see cmd/bd/proxied_server.go).\nfunc atomicWriteFile(path string, data []byte) error {\n\tdir := filepath.Dir(path)\n\ttmp, err := os.CreateTemp(dir, \".backup-tmp-*\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create temp file: %w\", err)\n\t}\n\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/.","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/backup_export.go#L89-L125","documentation":"atomicWriteFile writes the payload to the staged temp file; this wraps a tmp.Write failure. On error the temp file is closed and removed, leaving the original file untouched.","triggerScenarios":"tmp.Write(data) fails after a successful CreateTemp: disk filled up between create and write, quota exceeded, or the file descriptor became invalid (rare).","commonSituations":"Disk filling up mid-operation; user quota hit; container storage limit reached; I/O errors on failing hardware.","solutions":["Free disk space: df -h and clean up; retry the command.","Check user/container storage quotas.","If hardware I/O errors appear in dmesg, address the disk health issue.","Retry — the atomic design means no partial/corrupt backup_state.json is left behind."],"exampleFix":"// shell\ndf -h .   # verify free space, then retry\nbd sync","handlingStrategy":"retry","validationCode":"var st syscall.Statfs_t\nif err := syscall.Statfs(\".beads\", &st); err == nil {\n    freeBytes := st.Bavail * uint64(st.Bsize)\n    if freeBytes < 1<<20 { // need at least ~1MB headroom\n        return errors.New(\"insufficient disk space for backup state write\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := saveBackupState(dir, state); err != nil {\n    if strings.Contains(err.Error(), \"write temp file\") {\n        // likely ENOSPC — surface clearly and let caller free space / retry\n        return fmt.Errorf(\"disk may be full: %w\", err)\n    }\n    return err\n}","preventionTips":["Monitor disk space on volumes hosting .beads","Set alerts before volumes fill; quotas count too","Clean stale temp files (.backup-tmp-*) after crashes"],"tags":["go","filesystem","io","disk-full"],"backgroundTag":"disk-full","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}