micro-editor/micro · error

Error: %s is a directory and cannot be opened

Error message

Error: %s is a directory and cannot be opened

What it means

Returned by the buffer constructor path in internal/buffer/buffer.go:297 (NewBufferFromFile*) after os.Stat succeeds and the target is a directory. Micro buffers wrap regular file contents, so a directory cannot become a buffer and the open is refused before any read attempt. The path is included in the message.

Source

Thrown at internal/buffer/buffer.go:297

		var cursorPos []string
		filename, cursorPos = util.GetPathAndCursorPosition(filename)
		cmd.StartCursor, err = ParseCursorLocation(cursorPos)
		if err != nil {
			cmd.StartCursor = Loc{-1, -1}
		}
	}

	filename, err = util.ReplaceHome(filename)
	if err != nil {
		return nil, err
	}

	fileInfo, serr := os.Stat(filename)
	if serr != nil && !errors.Is(serr, fs.ErrNotExist) {
		return nil, serr
	}
	if serr == nil && fileInfo.IsDir() {
		return nil, errors.New("Error: " + filename + " is a directory and cannot be opened")
	}
	if serr == nil && !fileInfo.Mode().IsRegular() {
		return nil, errors.New("Error: " + filename + " is not a regular file and cannot be opened")
	}

	f, err := os.OpenFile(filename, os.O_WRONLY, 0)
	readonly := errors.Is(err, fs.ErrPermission)
	f.Close()

	file, err := os.Open(filename)
	if err == nil {
		defer file.Close()
	}

	var buf *Buffer
	if errors.Is(err, fs.ErrNotExist) {
		// File does not exist -- create an empty buffer with that name
		buf = NewBufferFromString("", filename, btype)

View on GitHub (pinned to 1c8b82b32e)

Solutions

  1. Pass a concrete file path: micro src/main.go instead of micro src
  2. Inside micro use :open with an actual filename; use Tab-completion to land on files, not dirs
  3. If you want directory navigation, install the filemanager plugin and open dirs through it
  4. In code, stat and branch before calling NewBufferFromFile (see validation snippet)

Example fix

// before
micro ~/projects
# Error: /home/u/projects is a directory and cannot be opened

// after
micro ~/projects/main.go
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight a path before buffer open
func openBufferSafe(path string) (*buffer.Buffer, error) {
    fi, err := os.Stat(path)
    if err == nil && fi.IsDir() {
        return nil, fmt.Errorf("%s is a directory — pass a file or use the filemanager plugin", path)
    }
    return buffer.NewBufferFromFile(path, buffer.BTDefault)
}

Try / catch

buf, err := buffer.NewBufferFromFile(path, buffer.BTDefault)
if err != nil {
    if strings.HasSuffix(err.Error(), "is a directory and cannot be opened") {
        // offer directory navigation instead of failing hard
        InfoBar.Error(err)
        return nil // non-fatal: user stays in current buffer
    }
    return nil, err
}

Prevention

When it happens

Trigger: micro ~/projects on the command line; :open . inside a running session; a path that used to be a file but was replaced by a directory (deleted then mkdir'd) before open; a trailing-slash typo like 'micro src/'.

Common situations: Muscle-memory from terminal: running 'micro .' expecting a file tree (micro has none built in); scripts globbing paths that resolve to directories; symlink swapping during deploy.

Related errors


AI-assisted analysis of micro-editor/micro@1c8b82b32e (2026-08-15). Data as JSON: /api/errors/066bf7e3c69312e1. Report an issue: GitHub.