{"id":"4e6bb90d6093fc87","repo":"gofiber/fiber","slug":"failed-to-check-directory-w","errorCode":null,"errorMessage":"failed to check directory: %w","messagePattern":"failed to check directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/response.go","lineNumber":153,"sourceCode":"\t}\n\n\treturn r.client.xmlUnmarshal(r.Body(), v)\n}\n\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}","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/client/response.go#L135-L171","documentation":"Returned by Response.Save (client/response.go:153) when os.Stat on the target file's directory fails with an error other than fs.ErrNotExist. Save first stats the parent directory; a non-not-exist error (e.g. permission denied, too many symlinks, I/O error) is surfaced here rather than silently attempting to create the file.","triggerScenarios":"Calling resp.Save(\"/path/to/file\") where stat-ing the parent directory errors for a reason other than 'does not exist' — permission denied on a directory component, ELOOP on a symlink chain, or a stale NFS handle.","commonSituations":"Writing to a path under a directory the process cannot traverse (permission denied); a broken symlink in the path; a read-only filesystem mount; SELinux/AppArmor denying stat.","solutions":["Check that every directory in the target path is traversable by the process user (execute permission).","Resolve symlinks in the path beforehand to detect loops or dead links.","Choose a target directory the process owns or has been granted write+traverse access to.","Inspect the wrapped error to distinguish permission issues from filesystem corruption."],"exampleFix":"// before — saving under a path the process can't traverse\nerr := resp.Save(\"/var/lib/app/data/body.json\")\n\n// after — verify the parent dir is accessible first\ndir := filepath.Dir(target)\nif info, err := os.Stat(dir); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"target dir unusable: %w\", err)\n}\nerr := resp.Save(target)","handlingStrategy":"validation","validationCode":"// Confirm the parent directory is traversable before saving.\nfunc dirAccessible(dir string) bool {\n    info, err := os.Stat(dir)\n    return err == nil && info.IsDir()\n}","typeGuard":null,"tryCatchPattern":"if info, err := os.Stat(filepath.Dir(path)); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"target directory unavailable: %w\", err)\n}\nreturn resp.Save(path)","preventionTips":["Ensure every directory in the target path is traversable (execute bit) by the app user.","Resolve symlinks beforehand to catch loops or dead links.","Write into directories the process owns or has been granted access to."],"tags":["client","save","filesystem","permissions"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}