{"record":{"id":"1e1da8caed812413","repo":"wavetermdev/waveterm","slug":"failed-to-stat-file-for-backup-w","errorCode":null,"errorMessage":"failed to stat file for backup: %w","messagePattern":"failed to stat file for backup: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/filebackup/filebackup.go","lineNumber":31,"sourceCode":"\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"github.com/wavetermdev/waveterm/pkg/wavebase\"\n)\n\nconst BackupRetentionPeriod = 5 * 24 * time.Hour\n\ntype BackupMetadata struct {\n\tFullPath  string `json:\"fullpath\"`\n\tTimestamp string `json:\"timestamp\"`\n\tPerm      string `json:\"perm\"`\n}\n\nfunc MakeFileBackup(absFilePath string) (string, error) {\n\tfileInfo, err := os.Stat(absFilePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to stat file for backup: %w\", err)\n\t}\n\n\tfileData, err := os.ReadFile(absFilePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to read file for backup: %w\", err)\n\t}\n\n\tdir := filepath.Dir(absFilePath)\n\tbasename := filepath.Base(absFilePath)\n\n\thash := sha256.Sum256([]byte(dir))\n\tdirHash8 := hex.EncodeToString(hash[:])[:8]\n\n\tuuidV7, err := uuid.NewV7()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to generate UUID: %w\", err)\n\t}\n\tuuidStr := uuidV7.String()","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/filebackup/filebackup.go#L13-L49","documentation":"MakeFileBackup snapshots a file before Wave modifies it (write/edit/delete text-file callbacks). It first calls os.Stat on the absolute path; if the file cannot be stat'd (missing, permission denied, or bad path), this wrapped error is returned and no backup is made, so the operation is aborted before modifying the file.","triggerScenarios":"os.Stat(absFilePath) fails: file already deleted (e.g. deleteTextFileCallback racing another delete), wrong/relative path passed, or permission denied on a parent directory.","commonSituations":"Two clients deleting/editing the same file concurrently; file removed outside Wave between listing and the edit; symlink to a non-existent target; case-sensitivity mismatch on path.","solutions":["Verify the file still exists before issuing the write/edit/delete (refresh the file listing)","Check path spelling and that it is absolute and on a mounted filesystem","Fix permissions on the file and its parent directories","If delete raced, treat the missing file as already-deleted and retry or ignore"],"exampleFix":"// before\nbackupPath, err := filebackup.MakeFileBackup(path)\n// after\nif _, err := os.Stat(path); os.IsNotExist(err) {\n    return nil // nothing to back up; file already gone\n}\nbackupPath, err := filebackup.MakeFileBackup(path)","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(absFilePath); err != nil {\n    // file missing/unreadable — skip backup or treat delete as already done\n}","typeGuard":null,"tryCatchPattern":"backupPath, err := filebackup.MakeFileBackup(path)\nif err != nil {\n    if os.IsNotExist(errors.Unwrap(err)) {\n        return nil // nothing to back up; file already gone\n    }\n    return err\n}","preventionTips":["Refresh file state before editing/deleting; don't operate on stale listings","Always pass absolute, resolved paths to MakeFileBackup","Check parent-directory permissions, not just file permissions","Handle concurrent modification: re-stat right before the operation"],"tags":["filesystem","backup","go","file-missing"],"backgroundTag":"file-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}