nats-io/nats-server · error

error opening config file: %v

Error message

error opening config file: %v

What it means

conf.ParseFile reads the config file with os.ReadFile and wraps any read failure in "error opening config file: %v". The library throws it whenever the file cannot be opened — missing path, permission problems, or a directory instead of a file. It is the first error the parser can produce and the underlying OS error is included in the message.

Source

Thrown at conf/parse.go:92

		return nil, err
	}
	return p.mapping, nil
}

// ParseWithChecks is equivalent to Parse but runs in pedantic mode.
func ParseWithChecks(data string) (map[string]any, error) {
	p, err := parse(data, "", true)
	if err != nil {
		return nil, err
	}
	return p.mapping, nil
}

// ParseFile is a helper to open file, etc. and parse the contents.
func ParseFile(fp string) (map[string]any, error) {
	data, err := os.ReadFile(fp)
	if err != nil {
		return nil, fmt.Errorf("error opening config file: %v", err)
	}

	p, err := parse(string(data), fp, false)
	if err != nil {
		return nil, err
	}
	return p.mapping, nil
}

// ParseFileWithChecks is equivalent to ParseFile but runs in pedantic mode.
func ParseFileWithChecks(fp string) (map[string]any, error) {
	data, err := os.ReadFile(fp)
	if err != nil {
		return nil, err
	}

	p, err := parse(string(data), fp, true)
	if err != nil {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Verify the file path exists: ls -l <path>, and use an absolute path
  2. Fix file permissions so the server's user can read the config
  3. Check that the path points to a file, not a directory
  4. If running under systemd/container, confirm the config is mounted and the WorkingDirectory is correct

Example fix

// before
conf, err := conf.ParseFile("nats.conf")
// after
if _, statErr := os.Stat("/etc/nats/nats.conf"); statErr != nil {
    log.Fatalf("config missing: %v", statErr)
}
conf, err := conf.ParseFile("/etc/nats/nats.conf")
Defensive patterns

Strategy: try-catch

Validate before calling

if fp == "" {
    return errors.New("config path required")
}
if fi, err := os.Stat(fp); err != nil {
    return fmt.Errorf("config not accessible: %w", err)
} else if fi.IsDir() {
    return fmt.Errorf("%s is a directory", fp)
}

Try / catch

cfg, err := conf.ParseFile(fp)
if err != nil {
    if strings.HasPrefix(err.Error(), "error opening config file") {
        log.Fatalf("cannot read config %q: %v — check path, permissions and working directory", fp, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling conf.ParseFile(path) (or starting the NATS server with -c) with a path that does not exist, a path without read permission, or a directory path; includes resolving to missing files.

Common situations: Typo in the -c flag path; running the server as a different user (systemd service) lacking read access; relative path resolved from the wrong working directory; mounted config not yet present in a container.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/d58c10e3a21b3737. Report an issue: GitHub.