micro-editor/micro · error

Error: %s is not a regular file and cannot be opened

Error message

Error: %s is not a regular file and cannot be opened

What it means

Returned by the same buffer constructor (internal/buffer/buffer.go:300) when os.Stat succeeds, the target is not a directory, but Mode().IsRegular() is false — i.e. character/block devices, FIFOs, Unix sockets and similar special files. Only regular files (or nonexistent paths, which create empty buffers) are openable; anything else is rejected with the path in the message.

Source

Thrown at internal/buffer/buffer.go:300

		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)
	} else if err != nil {
		return nil, err
	} else {

View on GitHub (pinned to 1c8b82b32e)

Solutions

  1. For stream-like sources, pipe instead: dmesg | micro (micro reads stdin when it's not a tty)
  2. Open the backing regular file, not the device node
  3. In code, require fi.Mode().IsRegular() before calling NewBufferFromFile (see validation snippet)

Example fix

// before
micro /dev/ttyUSB0
# Error: /dev/ttyUSB0 is not a regular file and cannot be opened

// after
cat /dev/ttyUSB0 | micro
Defensive patterns

Strategy: validation

Validate before calling

// Only regular files (or missing paths) reach NewBufferFromFile
func isRegularOrMissing(path string) bool {
    fi, err := os.Stat(path)
    if err != nil { return true }                    // new buffer will be created
    return fi.Mode().IsRegular()
}
if !isRegularOrMissing(p) { return fmt.Errorf("%s is a special file", p) }

Try / catch

buf, err := buffer.NewBufferFromFile(path, buffer.BTDefault)
if err != nil {
    if strings.HasSuffix(err.Error(), "is not a regular file and cannot be opened") {
        // devices/fifos: redirect users to piping
        InfoBar.Error(err.Error() + " — pipe instead: cmd | micro")
        return nil
    }
    return nil, err
}

Prevention

When it happens

Trigger: micro /dev/null, /dev/video0, /dev/tty, a named pipe created by mkfifo, or a unix socket file; :open /dev/urandom style probes.

Common situations: Trying to view device output in-editor ('micro /dev/ttyUSB0'); opening /dev/stdin or /dev/fd/N special files instead of piping (which micro supports via stdin: `cmd | micro`); container setups where a config path is a mounted socket.

Related errors


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