gofiber/fiber · error
failed to check directory: %w
Error message
failed to check directory: %w
What it means
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.
Source
Thrown at client/response.go:153
}
return r.client.xmlUnmarshal(r.Body(), v)
}
// Save writes the response body to a file or io.Writer.
// If a string path is provided, it creates directories if needed, then writes to a file.
// If an io.Writer is provided, it writes directly to it.
// When streaming is enabled, the body is read directly from the stream.
func (r *Response) Save(v any) error {
switch p := v.(type) {
case string:
file := filepath.Clean(p)
dir := filepath.Dir(file)
// Create directory if it doesn't exist
if _, err := os.Stat(dir); err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("failed to check directory: %w", err)
}
if err = os.MkdirAll(dir, 0o750); err != nil {
return fmt.Errorf("failed to create directory: %w", err)
}
}
// Create and write to file
outFile, err := os.Create(file)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
defer func() { _ = outFile.Close() }() //nolint:errcheck // not needed
// Use BodyStream() which handles both streaming and non-streaming cases
if _, err = io.Copy(outFile, r.BodyStream()); err != nil {
return fmt.Errorf("failed to write response body to file: %w", err)
}View on GitHub (pinned to 9a4c7e57fe)
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.
Example fix
// before — saving under a path the process can't traverse
err := resp.Save("/var/lib/app/data/body.json")
// after — verify the parent dir is accessible first
dir := filepath.Dir(target)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
return fmt.Errorf("target dir unusable: %w", err)
}
err := resp.Save(target) Defensive patterns
Strategy: validation
Validate before calling
// Confirm the parent directory is traversable before saving.
func dirAccessible(dir string) bool {
info, err := os.Stat(dir)
return err == nil && info.IsDir()
} Try / catch
if info, err := os.Stat(filepath.Dir(path)); err != nil || !info.IsDir() {
return fmt.Errorf("target directory unavailable: %w", err)
}
return resp.Save(path) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to create directory: %w
- failed to create file: %w
- open file error: %w
- failed to copy file data: %w
- failed to write response body to file: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/4e6bb90d6093fc87.json.
Report an issue: GitHub.