micro-editor/micro · error
Error: %s is a directory and cannot be saved
Error message
Error: %s is a directory and cannot be saved
What it means
Returned by (*Buffer).saveToFile (internal/buffer/buffer save.go:280) when os.Stat on the save target succeeds and the target is a directory. Micro only writes regular files, so saving over a directory path is refused before open/write. Note this fires for SaveAs targets and for the original path when it got replaced by a directory since the buffer was opened.
Source
Thrown at internal/buffer/save.go:280
b.insert(end, []byte{'\n'})
}
}
filename, err = util.ReplaceHome(filename)
if err != nil {
return err
}
newFile := false
fileInfo, err := os.Stat(filename)
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return err
}
newFile = true
}
if err == nil && fileInfo.IsDir() {
return errors.New("Error: " + filename + " is a directory and cannot be saved")
}
if err == nil && !fileInfo.Mode().IsRegular() {
return errors.New("Error: " + filename + " is not a regular file and cannot be saved")
}
absFilename := util.ResolvePath(filename)
// Get the leading path to the file | "." is returned if there's no leading path provided
if dirname := filepath.Dir(absFilename); dirname != "." {
// Check if the parent dirs don't exist
if _, statErr := os.Stat(dirname); errors.Is(statErr, fs.ErrNotExist) {
// Prompt to make sure they want to create the dirs that are missing
if b.Settings["mkparents"].(bool) {
// Create all leading dir(s) since they don't exist
if mkdirallErr := os.MkdirAll(dirname, os.ModePerm); mkdirallErr != nil {
// If there was an error creating the dirs
return mkdirallErr
}View on GitHub (pinned to 1c8b82b32e)
Solutions
- Give the full file path: :saveas /tmp/notes.txt (no trailing slash)
- If the original path became a directory: mv it aside or SaveAs to a new filename, then fix your tree
- In code, stat the destination and require !IsDir() before calling Save/SaveAs (see validation snippet)
Example fix
// before :saveas ~/projects/ # Error: /home/u/projects is a directory and cannot be saved // after :saveas ~/projects/main.go
Defensive patterns
Strategy: validation
Validate before calling
// Verify the save target is a writable regular-file slot before SaveAs
func saveTargetOk(path string) error {
fi, err := os.Stat(path)
if err != nil { return nil } // new file: fine
if fi.IsDir() { return fmt.Errorf("%s is a directory", path) }
if !fi.Mode().IsRegular() { return fmt.Errorf("%s is not a regular file", path) }
return nil
} Try / catch
if err := h.Buf.SaveAs(target); err != nil {
if strings.HasSuffix(err.Error(), "is a directory and cannot be saved") {
InfoBar.Error("append a filename: " + filepath.Join(target, "file.txt"))
return
}
return err
} Prevention
- Always SaveAs to a full file path — never a bare directory or trailing slash
- If the original file was replaced by a same-named directory, SaveAs to a new name and fix the tree
- Stat targets in scripts that generate :saveas commands
When it happens
Trigger: :saveas /tmp (existing dir), :saveas some/dir where some/dir exists as a directory; or the buffer's original file was deleted and a same-named directory created (common after 'rm x && mkdir x'), then Ctrl-s is pressed.
Common situations: Save dialogs/commands given a folder instead of a full file path; deployment scripts that turn a file location into a directory; typos with trailing slash: ':saveas backup/'
Related errors
- Error: %s is a directory and cannot be opened
- Error: %s is not a regular file and cannot be saved
- Error reading bindings.json file: %s
- Error: %s is not a regular file and cannot be opened
- Parent dirs don't exist, enable 'mkparents' for auto creatio
AI-assisted analysis of micro-editor/micro@1c8b82b32e (2026-08-15).
Data as JSON: /api/errors/406a6b90fdd1bbb1.
Report an issue: GitHub.