{"record":{"id":"6c4cb38364f76b0b","repo":"gofiber/fiber","slug":"failed-to-create-directory-w","errorCode":null,"errorMessage":"failed to create directory: %w","messagePattern":"failed to create directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/response.go","lineNumber":199,"sourceCode":"\n// Save writes the response body to a file or io.Writer.\n// If a string path is provided, it creates directories if needed, then writes to a file.\n// If an io.Writer is provided, it writes directly to it.\n// When streaming is enabled, the body is read directly from the stream.\nfunc (r *Response) Save(v any) error {\n\tswitch p := v.(type) {\n\tcase string:\n\t\tfile := filepath.Clean(p)\n\t\tdir := filepath.Dir(file)\n\n\t\t// Create directory if it doesn't exist\n\t\tif _, err := os.Stat(dir); err != nil {\n\t\t\tif !errors.Is(err, fs.ErrNotExist) {\n\t\t\t\treturn fmt.Errorf(\"failed to check directory: %w\", err)\n\t\t\t}\n\n\t\t\tif err = os.MkdirAll(dir, 0o750); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create directory: %w\", err)\n\t\t\t}\n\t\t}\n\n\t\t// Create and write to file\n\t\toutFile, err := os.Create(file)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create file: %w\", err)\n\t\t}\n\t\tdefer func() { _ = outFile.Close() }() //nolint:errcheck // not needed\n\n\t\t// Use BodyStream() which handles both streaming and non-streaming cases\n\t\tif _, err = io.Copy(outFile, r.BodyStream()); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write response body to file: %w\", err)\n\t\t}\n\n\t\treturn nil\n\n\tcase io.Writer:","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/response.go#L181-L217","documentation":"Response.Save attempts os.MkdirAll(dir, 0o750) when the target directory does not exist. This wraps a failure of that call: a parent component is a file (ENOTDIR), permission denied (EACCES), or read-only filesystem.","triggerScenarios":"The save path's parent doesn't exist and cannot be created; a parent in the chain is a regular file; the process cannot write to the location; mount is read-only.","commonSituations":"User-supplied download paths; containers with read-only volumes; chroot/jail missing a writable directory; path collision where an ancestor is a file.","solutions":["Use a save directory known to be writable by the process (e.g. os.TempDir()).","Resolve the full path and ensure no ancestor is a regular file before calling Save.","Mount a writable volume at the save location in containerized deployments."],"exampleFix":"// before\nif err := resp.Save(\"/var/lock/downloads/out.bin\"); err != nil { ... }\n\n// after\ndir := filepath.Join(os.TempDir(), \"downloads\")\n_ = os.MkdirAll(dir, 0o750)\nif err := resp.Save(filepath.Join(dir, \"out.bin\")); err != nil { ... }","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(dir, 0o750); err != nil {\n    return fmt.Errorf(\"cannot use save dir %q: %w\", dir, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write into a directory the process owns (e.g. under os.TempDir()).","Ensure no ancestor of the save path is a regular file.","Mount a writable volume in containers at the save path."],"tags":["client","response","save","filesystem","mkdir","permissions"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}