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

  1. Run golangci-lint from the repository/module root so relative path computation works
  2. Exclude the offending path (vendored, symlinked, generated) via issues.exclude-* settings
  3. Resolve symlinks so analyzed files live inside the project tree
  4. 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

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


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