golangci/golangci-lint · error

[%s] file open: %w

Error message

[%s] file open: %w

What it means

decodeYamlFile opens the target config file with os.Open before YAML-decoding it for schema validation. If the file cannot be opened, the error is wrapped as "[%s] file open: %w" including the filename. It is called from validateConfiguration during config verify.

Source

Thrown at pkg/commands/config_verify.go:96

func printValidationDetail(cmd *cobra.Command, detail *jsonschema.OutputUnit) {
	if detail.Error != nil {
		data, _ := json.Marshal(detail.Error)
		details, _ := strconv.Unquote(string(data))

		cmd.PrintErrf("jsonschema: %q does not validate with %q: %s\n",
			strings.ReplaceAll(strings.TrimPrefix(detail.InstanceLocation, "/"), "/", "."), detail.KeywordLocation, details)
	}

	for _, d := range detail.Errors {
		printValidationDetail(cmd, &d)
	}
}

func decodeYamlFile(filename string) (any, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("[%s] file open: %w", filename, err)
	}

	defer func() { _ = file.Close() }()

	var m any
	err = yaml.NewDecoder(file).Decode(&m)
	if err != nil {
		return nil, fmt.Errorf("[%s] YAML decode: %w", filename, err)
	}

	return m, nil
}

func decodeTomlFile(filename string) (any, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("[%s] file open: %w", filename, err)
	}

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Check the filename in the error and verify the file exists at that path (ls <path>)
  2. Run verify from the project root or pass an absolute path to the config file
  3. Fix file permissions if access is denied (chmod/chown)
  4. Ensure the path is a regular file, not a directory

Example fix

// before
$ golangci-lint config verify .golangci.yaml  # file is actually .golangci.yml
// [.golangci.yaml] file open: no such file or directory

// after
$ golangci-lint config verify .golangci.yml
Defensive patterns

Strategy: validation

Validate before calling

func assertReadableFile(path string) error {
    info, err := os.Stat(path)
    if err != nil {
        return fmt.Errorf("config file missing/unreachable: %w", err)
    }
    if info.IsDir() {
        return fmt.Errorf("%s is a directory, expected a file", path)
    }
    f, err := os.Open(path)
    if err != nil {
        return fmt.Errorf("no read permission on %s: %w", path, err)
    }
    _ = f.Close()
    return nil
}

Type guard

func isFileOpenError(err error) (string, bool) {
    var pe *os.PathError
    if errors.As(err, &pe) {
        return pe.Path, true
    }
    return "", false
}

Try / catch

m, err := decodeYamlFile(filename)
if err != nil {
    var pe *os.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, os.ErrNotExist) {
        return fmt.Errorf("config %s not found — check the path passed to verify", filename)
    }
    return fmt.Errorf("[%s] file open: %w", filename, err)
}

Prevention

When it happens

Trigger: os.Open(filename) fails inside decodeYamlFile — path doesn't exist, wrong permissions, or it's a directory — when running the verify flow on a .yaml/.yml/.json config.

Common situations: Typos in the config path passed to `config verify`; running from a different working directory; file deleted between edit and verify; restricted CI permissions.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02). Data as JSON: /api/errors/f3d7b7090d863a64. Report an issue: GitHub.