{"record":{"id":"86c74927e34b6e47","repo":"wavetermdev/waveterm","slug":"failed-to-read-file-w-86c749","errorCode":null,"errorMessage":"failed to read file: %w","messagePattern":"failed to read file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/fileutil/fileutil.go","lineNumber":354,"sourceCode":"}\n\nfunc ReplaceInFile(filePath string, edits []EditSpec) error {\n\tfileInfo, err := os.Stat(filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to stat file: %w\", err)\n\t}\n\n\tif !fileInfo.Mode().IsRegular() {\n\t\treturn fmt.Errorf(\"not a regular file: %s\", filePath)\n\t}\n\n\tif fileInfo.Size() > MaxEditFileSize {\n\t\treturn fmt.Errorf(\"file too large for editing: %d bytes (max: %d)\", fileInfo.Size(), MaxEditFileSize)\n\t}\n\n\tcontents, err := os.ReadFile(filePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read file: %w\", err)\n\t}\n\n\tmodifiedContents, err := ApplyEdits(contents, edits)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := os.WriteFile(filePath, modifiedContents, fileInfo.Mode()); err != nil {\n\t\treturn fmt.Errorf(\"failed to write file: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ReplaceInFilePartial applies edits incrementally up to the first failure.\n// Returns the results for each edit and writes the partially modified content.\nfunc ReplaceInFilePartial(filePath string, edits []EditSpec) ([]EditResult, error) {\n\tfileInfo, err := os.Stat(filePath)","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/fileutil/fileutil.go#L336-L372","documentation":"After size checks pass, ReplaceInFile reads the entire file with os.ReadFile; any read failure (I/O error, permission denied on the file, race where the file disappears) is wrapped with this message. No edits are applied.","triggerScenarios":"os.ReadFile(filePath) failing: no read permission on the file, file deleted between Stat and Read, I/O errors, or a file locked exclusively by another process.","commonSituations":"Editing files owned by root as a normal user; editing files that vanished due to a concurrent rotation/rename; NFS/network mount hiccups; read-only mounts.","solutions":["Check and fix file read permissions (chmod/chown).","Re-stat and retry — the file may have been deleted or rotated concurrently.","Verify the filesystem is not read-only or a failing mount (dmesg).","Copy the file locally before editing if it lives on an unreliable share."],"exampleFix":"// before\nfileutil.ReplaceInFile(\"/var/log/app.log\", edits) // permission denied\n\n// after\nif f, err := os.Open(path); err != nil {\n    return fmt.Errorf(\"cannot read %s: %w\", path, err)\n} else { f.Close() }\nfileutil.ReplaceInFile(path, edits)","handlingStrategy":"validation","validationCode":"// verify readability before attempting the edit\nf, err := os.Open(path)\nif err != nil {\n    return fmt.Errorf(\"file %s not readable: %w\", path, err)\n}\nf.Close()","typeGuard":null,"tryCatchPattern":"// Go: retry once on transient read errors\nif err := fileutil.ReplaceInFile(path, edits); err != nil {\n    if strings.Contains(err.Error(), \"failed to read file\") {\n        time.Sleep(100 * time.Millisecond)\n        return fileutil.ReplaceInFile(path, edits) // handle rotation race\n    }\n    return err\n}","preventionTips":["Check file read permissions for the running user","Avoid editing files subject to concurrent rotation/rename","Verify the mount is not read-only or degraded","Copy remote/NFS files locally before editing"],"tags":["go","filesystem","io"],"backgroundTag":"file-read-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}