{"record":{"id":"f483f9a3776736ba","repo":"wavetermdev/waveterm","slug":"failed-to-write-temp-file-q-w-also-failed-to-r","errorCode":null,"errorMessage":"failed to write temp file %q: %w (also failed to remove temp file: %v)","messagePattern":"failed to write temp file %q: %w \\(also failed to remove temp file: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/fileutil/fileutil.go","lineNumber":183,"sourceCode":"\t\tif mode&charDevice == charDevice {\n\t\t\treturn \"character-special\"\n\t\t}\n\t\tif mode&os.ModeDevice == os.ModeDevice {\n\t\t\treturn \"block-special\"\n\t\t}\n\t}\n\text := strings.ToLower(filepath.Ext(path))\n\tif mimeType, ok := StaticMimeTypeMap[ext]; ok {\n\t\treturn mimeType\n\t}\n\treturn \"\"\n}\n\nfunc AtomicWriteFile(fileName string, data []byte, perm os.FileMode) error {\n\ttmpFileName := fileName + TempFileSuffix\n\tif err := os.WriteFile(tmpFileName, data, perm); err != nil {\n\t\tif removeErr := os.Remove(tmpFileName); removeErr != nil && !os.IsNotExist(removeErr) {\n\t\t\treturn fmt.Errorf(\"failed to write temp file %q: %w (also failed to remove temp file: %v)\", tmpFileName, err, removeErr)\n\t\t}\n\t\treturn err\n\t}\n\tif err := os.Rename(tmpFileName, fileName); err != nil {\n\t\tif removeErr := os.Remove(tmpFileName); removeErr != nil && !os.IsNotExist(removeErr) {\n\t\t\treturn fmt.Errorf(\"failed to rename temp file %q to %q: %w (also failed to remove temp file: %v)\", tmpFileName, fileName, err, removeErr)\n\t\t}\n\t\treturn err\n\t}\n\treturn nil\n}\n\nvar (\n\tsystemBinDirs = []string{\n\t\t\"/bin/\",\n\t\t\"/usr/bin/\",\n\t\t\"/usr/local/bin/\",\n\t\t\"/opt/bin/\",","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/fileutil/fileutil.go#L165-L201","documentation":"AtomicWriteFile first writes the data to a temp file (<fileName>.tmp). If that write fails AND cleanup of the temp file also fails, the write error is wrapped together with the removal error so the developer sees both failures. The target file was never touched.","triggerScenarios":"Calling AtomicWriteFile where writing fileName+\".tmp\" fails (bad permissions, read-only dir, disk full, path is a directory) and the subsequent os.Remove of the temp file also fails with a non-NotNotExist error (e.g. permission denied on the directory).","commonSituations":"Writing to a directory without write permission; disk full so even unlink bookkeeping/attributes fail; temp file path colliding with a directory or a file owned by another user.","solutions":["Fix write permissions on the parent directory (chmod/chown) so both writing and removing the temp file succeed.","Check disk space (df) and free space on the filesystem holding the file.","Ensure fileName + \".tmp\" is not a directory or owned by another process; remove the stale temp file manually.","Retry the write after fixing the underlying condition, then re-run AtomicWriteFile."],"exampleFix":"// before\nerr := fileutil.AtomicWriteFile(\"/etc/hosts\", data, 0644) // permission denied, temp cleanup also denied\n\n// after\nif err := os.Chmod(filepath.Dir(target), 0755); err != nil { return err }\nerr := fileutil.AtomicWriteFile(target, data, 0644)","handlingStrategy":"try-catch","validationCode":"// precheck writability of the target directory\nd := filepath.Dir(fileName)\nif fi, err := os.Stat(d); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"bad target dir %s\", d)\n}\nif err := syscall.Access(d, unix.W_OK); err != nil {\n    return fmt.Errorf(\"dir %s not writable: %w\", d, err)\n}","typeGuard":null,"tryCatchPattern":"// Go: inspect wrapped errors\nif err := fileutil.AtomicWriteFile(f, data, 0644); err != nil {\n    if strings.Contains(err.Error(), \"failed to write temp file\") {\n        log.Printf(\"temp write failed (and cleanup failed): %v\", err)\n        // check permissions/disk space, remove stale <f>.tmp, retry\n    }\n}","preventionTips":["Ensure the target directory is writable by the process user","Monitor disk space on volumes holding config files","Remove stale *.tmp files after crashes","Avoid pointing AtomicWriteFile at paths owned by other users"],"tags":["go","filesystem","atomic-write"],"backgroundTag":"temp-file-write-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}