gofiber/fiber · error

failed to create file: %w

Error message

failed to create file: %w

What it means

Returned by Response.Save (client/response.go:164) when os.Create fails for the target file. After ensuring the parent directory exists, Save creates (or truncates) the file; failure — permission denied, invalid name, read-only filesystem, open-file limit — is wrapped here.

Source

Thrown at client/response.go:164

	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)
		}

		return nil

	case io.Writer:
		// Use BodyStream() which handles both streaming and non-streaming cases
		if _, err := io.Copy(p, r.BodyStream()); err != nil {
			return fmt.Errorf("failed to write response body to writer: %w", err)
		}
		// Close the writer if it implements io.WriteCloser
		if pc, ok := p.(io.WriteCloser); ok {
			_ = pc.Close() //nolint:errcheck // not needed

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Confirm the process can write in the target directory (permission bits / ownership).
  2. Ensure the path does not name an existing directory and the filename is valid.
  3. Raise the open-file ulimit if the process is exhausting descriptors.
  4. Use a writable volume for output files.

Example fix

// before — writing into a directory without write permission
err := resp.Save("/etc/app/out.json")

// after — write into a directory owned by the app user
err := resp.Save("/var/lib/myapp/out.json")  // ensure /var/lib/myapp is writable
Defensive patterns

Strategy: validation

Validate before calling

// Check the target file can be created before streaming.
func canCreate(path string) error {
    dir := filepath.Dir(path)
    if info, err := os.Stat(dir); err != nil || !info.IsDir() {
        return fmt.Errorf("parent dir unusable")
    }
    // probe writability
    tmp, err := os.CreateTemp(dir, ".probe-*")
    if err != nil {
        return err
    }
    tmp.Close(); os.Remove(tmp.Name())
    return nil
}

Try / catch

if err := resp.Save(path); err != nil {
    if strings.Contains(err.Error(), "failed to create file") {
        path = filepath.Join(os.TempDir(), filepath.Base(path))
        return resp.Save(path)
    }
    return err
}

Prevention

When it happens

Trigger: Calling resp.Save(path) where path cannot be created: permission denied in the directory, the path names a directory, an invalid filename (e.g. containing '/' on the OS, or NUL), read-only filesystem, or the process has hit its file-descriptor limit.

Common situations: App user lacks write permission in the target directory; path points at an existing directory; container on a read-only layer; too many open files (ulimit -n); filename contains illegal characters from unsanitized input.

Related errors


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