wavetermdev/waveterm · error

failed to read file: %w

Error message

failed to read file: %w

What it means

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.

Source

Thrown at pkg/util/fileutil/fileutil.go:354

}

func ReplaceInFile(filePath string, edits []EditSpec) error {
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return fmt.Errorf("failed to stat file: %w", err)
	}

	if !fileInfo.Mode().IsRegular() {
		return fmt.Errorf("not a regular file: %s", filePath)
	}

	if fileInfo.Size() > MaxEditFileSize {
		return fmt.Errorf("file too large for editing: %d bytes (max: %d)", fileInfo.Size(), MaxEditFileSize)
	}

	contents, err := os.ReadFile(filePath)
	if err != nil {
		return fmt.Errorf("failed to read file: %w", err)
	}

	modifiedContents, err := ApplyEdits(contents, edits)
	if err != nil {
		return err
	}

	if err := os.WriteFile(filePath, modifiedContents, fileInfo.Mode()); err != nil {
		return fmt.Errorf("failed to write file: %w", err)
	}

	return nil
}

// ReplaceInFilePartial applies edits incrementally up to the first failure.
// Returns the results for each edit and writes the partially modified content.
func ReplaceInFilePartial(filePath string, edits []EditSpec) ([]EditResult, error) {
	fileInfo, err := os.Stat(filePath)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check and fix file read permissions (chmod/chown).
  2. Re-stat and retry — the file may have been deleted or rotated concurrently.
  3. Verify the filesystem is not read-only or a failing mount (dmesg).
  4. Copy the file locally before editing if it lives on an unreliable share.

Example fix

// before
fileutil.ReplaceInFile("/var/log/app.log", edits) // permission denied

// after
if f, err := os.Open(path); err != nil {
    return fmt.Errorf("cannot read %s: %w", path, err)
} else { f.Close() }
fileutil.ReplaceInFile(path, edits)
Defensive patterns

Strategy: validation

Validate before calling

// verify readability before attempting the edit
f, err := os.Open(path)
if err != nil {
    return fmt.Errorf("file %s not readable: %w", path, err)
}
f.Close()

Try / catch

// Go: retry once on transient read errors
if err := fileutil.ReplaceInFile(path, edits); err != nil {
    if strings.Contains(err.Error(), "failed to read file") {
        time.Sleep(100 * time.Millisecond)
        return fileutil.ReplaceInFile(path, edits) // handle rotation race
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/86c74927e34b6e47. Report an issue: GitHub.