wavetermdev/waveterm · error
not a regular file: %s
Error message
not a regular file: %s
What it means
Returned when the path exists but is not a regular file (e.g. it is a directory, symlink to a device, socket, or pipe) and a regular file is required for the operation. The path is included via %s.
Source
Thrown at pkg/util/fileutil/fileutil.go:345
}
modifiedContents, results[i] = applyEdit(modifiedContents, edit, i)
if !results[i].Applied {
failed = true
}
}
return modifiedContents, results
}
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)View on GitHub (pinned to a4447c1563)
Solutions
- Point filePath at an actual file, not a directory or special file.
- If a directory was given, resolve to the concrete file inside it (e.g. the settings JSON).
- Check with os.Stat and FileInfo.Mode().IsRegular() before calling.
- Skip special files in any path-walking code that feeds ReplaceInFile.
Example fix
// before
fileutil.ReplaceInFile("/home/user/.config/wave", edits) // directory
// after
fi, _ := os.Stat(path)
if !fi.Mode().IsRegular() {
path = filepath.Join(path, "settings.json")
}
fileutil.ReplaceInFile(path, edits) Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(path)
if err == nil && !fi.Mode().IsRegular() {
return fmt.Errorf("refusing to edit non-regular file: %s", path)
} Try / catch
// Go: check message or pre-validate mode
if err := fileutil.ReplaceInFile(path, edits); err != nil {
if strings.Contains(err.Error(), "not a regular file") {
return fmt.Errorf("pass a concrete file path, not %s", path)
}
} Prevention
- Never pass directories or /dev, /proc, /sys paths to file-editing APIs
- Check FileInfo.Mode().IsRegular() after every Stat
- When expanding user input or globs, filter to regular files
- Resolve directories to a concrete file (e.g. dir + settings.json)
When it happens
Trigger: Calling ReplaceInFile with a directory path, a device node (/dev/...), a named pipe, or a unix socket as filePath.
Common situations: Passing a directory where a file was expected (e.g. ~/.config/wave instead of a settings file); resolving a glob or user input to a special file; editing paths under /proc or /sys.
Related errors
- path is not a directory
- path is a directory, not an image file
- invalid AIMessage: %w
- part %d: text type requires non-empty text field
- failed to expand path: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/dffbaed631e930bd.
Report an issue: GitHub.