{"record":{"id":"9408065b6b6c8e5a","repo":"golangci/golangci-lint","slug":"can-t-create-output-for-s-w","errorCode":null,"errorMessage":"can't create output for %s: %w","messagePattern":"can't create output for (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/printers/printer.go","lineNumber":76,"sourceCode":"\t\tstdOut:     logutils.StdOut,\n\t\tstdErr:     logutils.StdErr,\n\t}, nil\n}\n\n// Print prints issues based on the formats defined.\n//\n//nolint:gocyclo,funlen // the complexity is related to the number of formats.\nfunc (c *Printer) Print(issues []*result.Issue) error {\n\tif c.cfg.IsEmpty() {\n\t\tc.cfg.Text.Path = outputStdOut\n\t}\n\n\tvar printers []issuePrinter\n\n\tif c.cfg.Text.Path != \"\" {\n\t\tw, closer, err := c.createWriter(&c.cfg.Text.SimpleFormat)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"can't create output for %s: %w\", c.cfg.Text.Path, err)\n\t\t}\n\n\t\tdefer closer()\n\n\t\tprinters = append(printers, NewText(c.log, w, &c.cfg.Text))\n\t}\n\n\tif c.cfg.JSON.Path != \"\" {\n\t\tw, closer, err := c.createWriter(&c.cfg.JSON)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"can't create output for %s: %w\", c.cfg.JSON.Path, err)\n\t\t}\n\n\t\tdefer closer()\n\n\t\tprinters = append(printers, NewJSON(w, c.reportData))\n\t}\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/pkg/printers/printer.go#L58-L94","documentation":"Printer.Print wraps any error returned by createWriter for the text output path. createWriter fails when it cannot MkdirAll the parent directory or cannot os.OpenFile the report file (O_CREATE|O_TRUNC|O_WRONLY, mode 0644); relative paths are resolved against basePath first.","triggerScenarios":"output.formats.text.path set to a file path that cannot be created: parent directory missing/unwritable, path is an existing directory, read-only filesystem, or permission denied; createWriter returns the os error which is wrapped here.","commonSituations":"CI containers with read-only workspaces, output paths pointing into nonexistent mount points, path is a directory (e.g. 'out/' or 'reports'), running as non-root user without write perms, Windows-invalid path characters, SELinux/AppArmor denials.","solutions":["Check the wrapped os error: fix permissions (chmod/chown) or create the parent directory for the configured output path","Point output.formats.text.path to a writable file (not a directory), or use 'stdout'/'stderr' to stream to the terminal","In containers/CI, mount or set a writable output directory and pass an absolute path","Verify basePath: relative paths are joined with basePath, so run from the expected working directory or use an absolute path"],"exampleFix":"// before (.golangci.yml)\noutput:\n  formats:\n    text:\n      path: reports/\n// after\noutput:\n  formats:\n    text:\n      path: reports/lint.txt # must be a writable FILE path","handlingStrategy":"validation","validationCode":"p := filepath.Join(basePath, cfg.Output.Formats.Text.Path)\nif p != \"stdout\" && p != \"stderr\" {\n\tif err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {\n\t\treturn fmt.Errorf(\"text output dir not writable: %w\", err)\n\t}\n\tif fi, err := os.Stat(p); err == nil && fi.IsDir() {\n\t\treturn fmt.Errorf(\"%s is a directory, expected a file\", p)\n\t}\n\tf, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0o644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"text output not writable: %w\", err)\n\t}\n\tf.Close()\n}","typeGuard":null,"tryCatchPattern":"if err := p.Print(issues); err != nil {\n\tvar perr *fs.PathError\n\tif errors.As(err, &perr) && strings.Contains(err.Error(), \"can't create output\") {\n\t\tlog.Printf(\"report path %s unwritable (%v); falling back to stdout\", perr.Path, perr.Err)\n\t}\n}","preventionTips":["Always point output paths at files, never directories","Use 'stdout'/'stderr' literals when a file is unnecessary","Pre-create and permission-check report directories in CI before running golangci-lint","Prefer absolute paths or run from a known working directory so basePath joining is predictable"],"tags":["io","file-permissions","output","golangci-lint"],"backgroundTag":"output-file-create-failed","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}