golangci/golangci-lint · error
can't open file %s: %w
Error message
can't open file %s: %w
What it means
When computing line-length (lll) issues, golangci-lint reopens each source file from disk (os.Open on position.Filename). If the file can't be opened — missing, permission denied, or path issues — getLLLIssuesForFile wraps the OS error with this message and aborts the linter run.
Source
Thrown at pkg/golinters/lll/lll.go:60
if err != nil {
return err
}
}
return nil
}
func getLLLIssuesForFile(pass *analysis.Pass, file *ast.File, maxLineLen int, tabSpaces string) error {
position, isGoFile := goanalysis.GetGoFilePosition(pass, file)
if !isGoFile {
return nil
}
nonAdjPosition := pass.Fset.PositionFor(file.Pos(), false)
f, err := os.Open(position.Filename)
if err != nil {
return fmt.Errorf("can't open file %s: %w", position.Filename, err)
}
defer f.Close()
ft := pass.Fset.File(file.Pos())
lineNumber := 0
multiImportEnabled := false
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lineNumber++
line := scanner.Text()
line = strings.ReplaceAll(line, "\t", tabSpaces)
if strings.HasPrefix(line, goCommentDirectivePrefix) {
continueView on GitHub (pinned to ed7a235d2d)
Solutions
- Check the file exists and is readable: ls -l <file> and fix permissions (chmod/chown) or restore the file (git checkout -- <file>)
- Regenerate deleted generated files before running golangci-lint
- Run golangci-lint from the module root so relative paths resolve
- Check symlink targets exist; fix or remove broken symlinks
Example fix
# before $ golangci-lint run # can't open file /path/to/generated_gen.go: no such file or directory # after $ make generate # regenerate the missing file $ golangci-lint run
Defensive patterns
Strategy: try-catch
Validate before calling
import fs from 'node:fs'
for (const f of filesToLint) {
try { fs.accessSync(f, fs.constants.R_OK) } catch (e) {
throw new Error(`lll precondition failed: ${f} not readable (${e.message})`)
}
} Type guard
const isReadableFile = (p) => { try { return fs.statSync(p).isFile() && !!(fs.accessSync(p, fs.constants.R_OK) ?? true) } catch { return false } } Try / catch
try {
await runGolangciLint(['--enable=lll'])
} catch (e) {
if (/can't open file .*: /.test(String(e))) {
// recover file (git checkout / regenerate) and retry once
await restoreMissingFiles(); await runGolangciLint(['--enable=lll'])
} else { throw e }
} Prevention
- Regenerate generated files before linting (make generate in CI)
- Run golangci-lint from the module root with the full checkout present
- Check file permissions and symlink targets in containerized lint jobs
- Restore deleted files with git checkout before re-running lint
When it happens
Trigger: The file referenced by the AST position no longer exists or isn't readable at lint time: deleted/renamed between generation and lint, unreadable permissions, symlink to nonexistent target, running in a container without the file mounted.
Common situations: Generated code files removed before linting, read-only or root-owned checkout (permission denied), linting outside the module where relative paths break, cgo/generated files with unusual paths.
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
- can't write heap profile: %w
- get base path: %w
- error getting working directory: %w
- Can't get working dir: %s
- the configuration contains invalid elements
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/dcc87bfa9a1db20f.
Report an issue: GitHub.