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

  1. Check that every directory in the target path is traversable by the process user (execute permission).
  2. Resolve symlinks in the path beforehand to detect loops or dead links.
  3. Choose a target directory the process owns or has been granted write+traverse access to.
  4. 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

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


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/4e6bb90d6093fc87.json. Report an issue: GitHub.