valyala/fasthttp · error

error when copying form file %q (%q): %w

Error message

error when copying form file %q (%q): %w

What it means

fasthttp wraps the error from copying the form file's contents into the multipart writer part (copyZeroAlloc) when building a multipart/form-data body. It reports which field/filename failed to stream. The file handle is closed before returning.

Source

Thrown at http.go:1255

				return fmt.Errorf("cannot write form field %q value %q: %w", k, v, err)
			}
		}
	}

	// marshal files
	for k, fvv := range f.File {
		for _, fv := range fvv {
			vw, err := mw.CreatePart(fv.Header)
			if err != nil {
				return fmt.Errorf("cannot create form file %q (%q): %w", k, fv.Filename, err)
			}
			fh, err := fv.Open()
			if err != nil {
				return fmt.Errorf("cannot open form file %q (%q): %w", k, fv.Filename, err)
			}
			if _, err = copyZeroAlloc(vw, fh); err != nil {
				_ = fh.Close()
				return fmt.Errorf("error when copying form file %q (%q): %w", k, fv.Filename, err)
			}
			if err = fh.Close(); err != nil {
				return fmt.Errorf("cannot close form file %q (%q): %w", k, fv.Filename, err)
			}
		}
	}

	if err := mw.Close(); err != nil {
		return fmt.Errorf("error when closing multipart form writer: %w", err)
	}

	return nil
}

func readMultipartForm(r io.Reader, boundary string, size, maxInMemoryFileSize int) (*multipart.Form, error) {
	// Do not care about memory allocations here, since they are tiny
	// compared to multipart data (aka multi-MB files) usually sent
	// in multipart/form-data requests.

View on GitHub (pinned to c96f600972)

Solutions

  1. Check the wrapped cause for the real I/O error (permission, file not found, etc.).
  2. Ensure the file still exists and is readable at request time, not just at SetFormFile time.
  3. If using a custom io.Reader, make sure it returns io.EOF instead of an error at end of stream.
  4. Open the file fresh just before the request instead of holding a stale handle.

Example fix

// before
f, _ := os.Open(path) // opened early, may be deleted later
req.SetFormFileCreate("upload", f.Name())
// after
if _, err := os.Stat(path); err != nil {
    return fmt.Errorf("form file missing: %w", err)
}
req.SetFormFileCreate("upload", path)
if err := client.Do(req, resp); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.Open(path)
if err != nil { return err }
if _, err := f.Stat(); err != nil { f.Close(); return err }
f.Close()

Type guard

func isReadableFile(path string) bool {
    f, err := os.Open(path)
    if err != nil { return false }
    f.Close()
    return true
}

Try / catch

if err := client.Do(req, resp); err != nil {
    if strings.Contains(err.Error(), "error when copying form file") {
        return fmt.Errorf("upload source failed: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Writing a request whose multipartForm contains a file field whose Open() reader returns an I/O error (e.g. file deleted after being registered via SetFormFileCreate, disk read failure, custom io.Reader erroring mid-copy).

Common situations: Registering an os.File with SetFormFileCreate and the file is removed/renamed before client.Do; reading from a failing network or pipe reader; permission denied on the underlying file at read time.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/81b9bfbc9a68df28. Report an issue: GitHub.