golangci/golangci-lint · error
failed to get shortest rel path for %q: %w
Error message
failed to get shortest rel path for %q: %w
What it means
The dupl linter wrapper in golangci-lint reports each duplicate-code issue with a relative path for readability. Before formatting the issue text it calls fsutils.ShortestRelPath on the duplicated-to file; if that fails, runDupl aborts with 'failed to get shortest rel path for %q'.
Source
Thrown at pkg/golinters/dupl/dupl.go:67
WithLoadMode(goanalysis.LoadModeSyntax)
}
func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]*goanalysis.Issue, error) {
issues, err := duplAPI.Run(internal.GetGoFileNames(pass), settings.Threshold)
if err != nil {
return nil, err
}
if len(issues) == 0 {
return nil, nil
}
res := make([]*goanalysis.Issue, 0, len(issues))
for _, i := range issues {
toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "")
if err != nil {
return nil, fmt.Errorf("failed to get shortest rel path for %q: %w", i.To.Filename(), err)
}
dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd())
text := fmt.Sprintf("%d-%d lines are duplicate of %s",
i.From.LineStart(), i.From.LineEnd(),
internal.FormatCode(dupl))
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.From.Filename(),
Line: i.From.LineStart(),
},
LineRange: &result.Range{
From: i.From.LineStart(),
To: i.From.LineEnd(),
},
Text: text,
FromLinter: linterName,View on GitHub (pinned to ed7a235d2d)
Solutions
- Run golangci-lint from the repository/module root so relative path computation works
- Exclude the offending path (vendored, symlinked, generated) via issues.exclude-* settings
- Resolve symlinks so analyzed files live inside the project tree
- Update golangci-lint if path handling (Windows/network paths) is the issue
Example fix
// run from module root instead of subdir // before: cd src && golangci-lint run // after cd /repo/root && golangci-lint run
Defensive patterns
Strategy: fallback
Validate before calling
// Before running dupl-based tooling, ensure CWD is the module root:
if _, err := os.Stat("go.mod"); err != nil {
return fmt.Errorf("run from the module root so relative paths resolve: %w", err)
} Try / catch
issues, err := runDupl(pass, issues)
if err != nil && strings.Contains(err.Error(), "shortest rel path") {
// fall back to running from repo root or excluding the path
log.Warnf("dupl path resolution failed: %v", err)
return nil, nil
} Prevention
- Always invoke golangci-lint from the repository root (CI: working-directory: .)
- Avoid symlinking source trees outside the module
- Exclude vendored/generated paths via issues.exclude-* so paths stay in-tree
When it happens
Trigger: runDupl processed dupl issues and fsutils.ShortestRelPath(i.To.Filename(), "") returned an error — typically the reported file is not under the current working directory / module root, or path resolution failed (symlinks, unusual paths).
Common situations: Running golangci-lint from a directory outside the analyzed module, analyzed files behind symlinks or on different mount points, duplicate paths appearing via vendored or generated files outside the project root.
Related errors
- get base path: %w
- the configuration contains invalid elements
- unsupported configuration format
- the configuration contains invalid elements
- parallel golangci-lint is running
AI-assisted analysis of golangci/golangci-lint@ed7a235d2d (2026-09-02).
Data as JSON: /api/errors/9b80be456b0fc0ed.
Report an issue: GitHub.