golangci/golangci-lint · error

can't get file %s contents: %w

Error message

can't get file %s contents: %w

What it means

runMisspellOnFile reads the raw file from disk (using the non-adjusted position filename so cgo files resolve correctly) so the misspell replacer can scan comments and strings. If the OS read fails, the error is wrapped with the file path and aborts the misspell pass.

Source

Thrown at pkg/golinters/misspell/misspell.go:86

	}

	// It can panic.
	replacer.Compile()

	return replacer, nil
}

func runMisspellOnFile(pass *analysis.Pass, file *ast.File, replacer *misspell.Replacer, mode string) error {
	position, isGoFile := goanalysis.GetGoFilePosition(pass, file)
	if !isGoFile {
		return nil
	}

	// Uses the non-adjusted file to work with cgo:
	// if we read the real file, the positions are wrong in some cases.
	fileContent, err := pass.ReadFile(pass.Fset.PositionFor(file.Pos(), false).Filename)
	if err != nil {
		return fmt.Errorf("can't get file %s contents: %w", position.Filename, err)
	}

	// `r.ReplaceGo` doesn't find issues inside strings: it searches only inside comments.
	// `r.Replace` searches all words: it treats input as a plain text.
	// The standalone misspell tool uses `r.Replace` by default.
	var replace func(input string) (string, []misspell.Diff)
	switch strings.ToLower(mode) {
	case "restricted":
		replace = replacer.ReplaceGo
	default:
		replace = replacer.Replace
	}

	f := pass.Fset.File(file.Pos())

	_, diffs := replace(string(fileContent))

	for _, diff := range diffs {

View on GitHub (pinned to ed7a235d2d)

Solutions

  1. Confirm the file exists and is readable at the reported path; fix permissions (chmod/chown).
  2. Re-run the linter to rule out a transient race with code generation or cleanup.
  3. Exclude generated/temporary files via skip-files so misspell doesn't read them.
  4. Check the wrapped %w cause for the exact OS error (ENOENT, EACCES, etc.) and fix storage/mount issues accordingly.

Example fix

# before: linting a generated dir that is deleted mid-run
linters-settings:
  misspell: {}
# after
issues:
  exclude-dirs:
    - generated-temp
  exclude-files:
    - ".+\\.pb\\.go$"
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.ReadFile(path); err != nil {
    return fmt.Errorf("file %s unreadable before lint: %w", path, err)
}

Try / catch

err := runMisspell(...)
if err != nil && strings.Contains(err.Error(), "can't get file") {
    // check wrapped cause: os.IsNotExist / permission, then skip or fix perms
}

Prevention

When it happens

Trigger: pass.ReadFile fails for the file at pass.Fset.PositionFor(file.Pos(), false).Filename — file deleted/moved after parsing, permission denied, or I/O error on a network/removable drive.

Common situations: Files removed between lint start and run (race with build cleanup), unreadable files due to permissions or encryption, linting over flaky network mounts or Docker volume races in CI.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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