{"record":{"id":"83a6e62d03626a17","repo":"golangci/golangci-lint","slug":"can-t-get-working-dir-s","errorCode":null,"errorMessage":"Can't get working dir: %s","messagePattern":"Can't get working dir: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/result/processors/path_shortener.go","lineNumber":22,"sourceCode":"\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/golangci/golangci-lint/v2/pkg/fsutils\"\n\t\"github.com/golangci/golangci-lint/v2/pkg/result\"\n)\n\nvar _ Processor = (*PathShortener)(nil)\n\n// PathShortener modifies text of the reports to reduce file path inside the text.\n// It uses the rooted path name corresponding to the current directory (`wd`).\ntype PathShortener struct {\n\twd string\n}\n\nfunc NewPathShortener() *PathShortener {\n\twd, err := fsutils.Getwd()\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Can't get working dir: %s\", err))\n\t}\n\n\treturn &PathShortener{wd: wd}\n}\n\nfunc (PathShortener) Name() string {\n\treturn \"path_shortener\"\n}\n\nfunc (p PathShortener) Process(issues []*result.Issue) ([]*result.Issue, error) {\n\treturn transformIssues(issues, func(issue *result.Issue) *result.Issue {\n\t\tnewIssue := issue\n\t\tnewIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd+\"/\", \"\")\n\t\tnewIssue.Text = strings.ReplaceAll(newIssue.Text, p.wd, \"\")\n\t\treturn newIssue\n\t}), nil\n}\n","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/result/processors/path_shortener.go#L4-L40","documentation":"NewPathShortener panics immediately if it cannot determine the current working directory via fsutils.Getwd, since path shortening is meaningless without it. Unlike errors 264, this constructor fails hard via panic rather than returning an error.","triggerScenarios":"Constructing NewPathShortener (during NewRunner) while os.Getwd fails: the current directory was deleted, or the process lacks permission to stat its cwd.","commonSituations":"Executing golangci-lint from a removed temp/build directory; test harnesses deleting the cwd mid-run; restricted sandboxes/containers where cwd lookup fails.","solutions":["Run golangci-lint from a valid, existing directory (cd into the project)","Recreate the deleted working directory before running the linter","Fix sandbox/permission settings so the process can access its current directory","If embedding the library, ensure NewPathShortener is only called after confirming os.Getwd() works"],"exampleFix":"// before\nos.RemoveAll(tmpDir) // still cwd\np := processors.NewPathShortener() // panics\n// after\nos.Chdir(projectDir)\nos.RemoveAll(tmpDir)\np := processors.NewPathShortener()","handlingStrategy":"try-catch","validationCode":"if _, err := os.Getwd(); err != nil {\n    // do not construct runners/shorteners from a dead cwd\n    os.Chdir(\"/\") // or the project dir\n}","typeGuard":null,"tryCatchPattern":"func safeRun() (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            if s, ok := r.(string); ok && strings.HasPrefix(s, \"Can't get working dir\") {\n                err = fmt.Errorf(\"cwd unavailable: %s\", s)\n            } else { panic(r) }\n        }\n    }()\n    processors.NewPathShortener()\n    return nil\n}","preventionTips":["Never delete the directory a running linter process uses as cwd","Confirm os.Getwd() succeeds before embedding golangci-lint processors","Run lint steps before cleanup steps in build scripts","Chdir to a stable project path early in wrapper scripts/tests"],"tags":["golangci-lint","panic","working-directory","filesystem"],"backgroundTag":"working-directory-unavailable","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}