antonmedv/fx · error

<non-PathError from os.Open(filePath)> (panic(err))

Error message

<non-PathError from os.Open(filePath)> (panic(err))

What it means

The open() helper opens the input file with os.Open. Expected failures (os.PathError: file not found, permission denied) print the error and exit(1); any other error type panics. This panic means os.Open failed in a way that is not a path-related error — rare, e.g. too many open files or an OS-level fault.

Source

Thrown at utils.go:38

func lookup(names []string, defaultEditor string) string {
	for _, name := range names {
		env, ok := os.LookupEnv(name)
		if ok && env != "" {
			return env
		}
	}
	return defaultEditor
}

func open(filePath string, flagYaml, flagToml *bool) *os.File {
	f, err := os.Open(filePath)
	if err != nil {
		var pathError *fs.PathError
		if errors.As(err, &pathError) {
			println(err.Error())
			os.Exit(1)
		} else {
			panic(err)
		}
	}
	fileName := path.Base(filePath)
	hasYamlExt, _ := regexp.MatchString(`(?i)\.ya?ml$`, fileName)
	hasTomlExt, _ := regexp.MatchString(`(?i)\.toml$`, fileName)
	if !*flagYaml && hasYamlExt {
		*flagYaml = true
	}
	if !*flagToml && hasTomlExt {
		*flagToml = true
	}
	return f
}

func regexCase(code string) (string, bool) {
	if strings.HasSuffix(code, "/i") {
		return code[:len(code)-2], true
	} else if strings.HasSuffix(code, "/") {

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Check and raise the file-descriptor limit (ulimit -n) if EMFILE is the cause
  2. Close other open files/handles in the process before calling open()
  3. Retry the command — some failures are transient resource exhaustion
  4. Convert the panic to a graceful exit for unexpected error types

Example fix

// before
} else {
	panic(err)
}
// after
} else {
	println(err.Error())
	os.Exit(1)
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-check file accessibility before invoking fx
f, err := os.Open(filePath)
if err != nil {
	return fmt.Errorf("cannot open %s: %w", filePath, err)
}
f.Close()

Type guard

func isOpenable(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	f.Close()
	return true
}

Try / catch

// recover if calling open() indirectly through fx
func safeRun(args []string) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("fx open failed: %v", r)
		}
	}()
	return callMain(args)
}

Prevention

When it happens

Trigger: os.Open(filePath) returns a non-nil error that is not *fs.PathError — e.g. EMFILE (too many open files), ENOMEM, or errors from unusual file systems not wrapped in PathError.

Common situations: Hitting the file-descriptor limit when many files are open; running with a depleted ulimit; exotic FUSE/network filesystems returning non-standard errors.

Related errors


AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02). Data as JSON: /api/errors/4ed55e00e9c75a3a. Report an issue: GitHub.