{"record":{"id":"709010365c336a70","repo":"gofiber/fiber","slug":"failed-to-create-file-w","errorCode":null,"errorMessage":"failed to create file: %w","messagePattern":"failed to create file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/response.go","lineNumber":206,"sourceCode":"\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:\n\t\t// Use BodyStream() which handles both streaming and non-streaming cases\n\t\tif _, err := io.Copy(p, r.BodyStream()); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write response body to writer: %w\", err)\n\t\t}\n\t\t// Close the writer if it implements io.WriteCloser\n\t\tif pc, ok := p.(io.WriteCloser); ok {\n\t\t\t_ = pc.Close() //nolint:errcheck // not needed","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/client/response.go#L188-L224","documentation":"After ensuring the directory exists, Response.Save calls os.Create(file). This wraps a failure of that call: permission denied, the path names a directory, invalid characters, or read-only filesystem.","triggerScenarios":"The final path component is a directory; the process lacks write permission on the directory; the filename contains illegal characters (NUL, slashes on Windows); the filesystem is read-only.","commonSituations":"Passing a directory path as the save target; write-protected mounts; user-supplied filenames with path separators; running as a UID without write rights.","solutions":["Sanitize the filename — reject path separators and control characters, ensure it is not an existing directory.","Write into a directory the process owns.","If overwriting, ensure the existing file is writable and not a directory."],"exampleFix":"// before\nif err := resp.Save(filepath.Join(dir, userInput)); err != nil { ... }\n\n// after\nif strings.ContainsAny(userInput, \"/\\\") || userInput == \"\" {\n    return errors.New(\"invalid filename\")\n}\nif err := resp.Save(filepath.Join(dir, userInput)); err != nil { ... }","handlingStrategy":"validation","validationCode":"if strings.ContainsAny(name, \"/\\\") || name == \"\" {\n    return errors.New(\"invalid filename\")\n}\nif info, err := os.Stat(name); err == nil && info.IsDir() {\n    return errors.New(\"save target is a directory\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sanitize user-supplied filenames (reject separators and control chars).","Write only into directories writable by the process UID.","Ensure the target is not a directory before overwrite."],"tags":["client","response","save","filesystem","create-file","validation"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}