{"record":{"id":"406a6b90fdd1bbb1","repo":"micro-editor/micro","slug":"error-s-is-a-directory-and-cannot-be-saved","errorCode":null,"errorMessage":"Error: %s is a directory and cannot be saved","messagePattern":"Error: (.+?) is a directory and cannot be saved","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/buffer/save.go","lineNumber":280,"sourceCode":"\t\t\tb.insert(end, []byte{'\\n'})\n\t\t}\n\t}\n\n\tfilename, err = util.ReplaceHome(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tnewFile := false\n\tfileInfo, err := os.Stat(filename)\n\tif err != nil {\n\t\tif !errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn err\n\t\t}\n\t\tnewFile = true\n\t}\n\tif err == nil && fileInfo.IsDir() {\n\t\treturn errors.New(\"Error: \" + filename + \" is a directory and cannot be saved\")\n\t}\n\tif err == nil && !fileInfo.Mode().IsRegular() {\n\t\treturn errors.New(\"Error: \" + filename + \" is not a regular file and cannot be saved\")\n\t}\n\n\tabsFilename := util.ResolvePath(filename)\n\n\t// Get the leading path to the file | \".\" is returned if there's no leading path provided\n\tif dirname := filepath.Dir(absFilename); dirname != \".\" {\n\t\t// Check if the parent dirs don't exist\n\t\tif _, statErr := os.Stat(dirname); errors.Is(statErr, fs.ErrNotExist) {\n\t\t\t// Prompt to make sure they want to create the dirs that are missing\n\t\t\tif b.Settings[\"mkparents\"].(bool) {\n\t\t\t\t// Create all leading dir(s) since they don't exist\n\t\t\t\tif mkdirallErr := os.MkdirAll(dirname, os.ModePerm); mkdirallErr != nil {\n\t\t\t\t\t// If there was an error creating the dirs\n\t\t\t\t\treturn mkdirallErr\n\t\t\t\t}","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/micro-editor/micro/blob/1c8b82b32e408a5faf340039ed92d5266bea3293/internal/buffer/save.go#L262-L298","documentation":"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.","triggerScenarios":":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.","commonSituations":"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/'","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)"],"exampleFix":"// before\n:saveas ~/projects/\n# Error: /home/u/projects is a directory and cannot be saved\n\n// after\n:saveas ~/projects/main.go","handlingStrategy":"validation","validationCode":"// Verify the save target is a writable regular-file slot before SaveAs\nfunc saveTargetOk(path string) error {\n    fi, err := os.Stat(path)\n    if err != nil { return nil }              // new file: fine\n    if fi.IsDir() { return fmt.Errorf(\"%s is a directory\", path) }\n    if !fi.Mode().IsRegular() { return fmt.Errorf(\"%s is not a regular file\", path) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := h.Buf.SaveAs(target); err != nil {\n    if strings.HasSuffix(err.Error(), \"is a directory and cannot be saved\") {\n        InfoBar.Error(\"append a filename: \" + filepath.Join(target, \"file.txt\"))\n        return\n    }\n    return err\n}","preventionTips":["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"],"tags":["save","filesystem","path","directory","io"],"backgroundTag":null,"analyzedSha":"1c8b82b32e408a5faf340039ed92d5266bea3293","analyzedAt":"2026-08-15T20:01:45.134Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}