gofiber/fiber · error

write formdata error

Error message

write formdata error: %w

What it means

writeMultipartBody iterates req.formData and calls mw.WriteField for each key/value. This wraps the first WriteField failure, which comes from the underlying body writer rejecting bytes (encoding issue, writer closed, buffer overflow).

Solutions

  1. Inspect the wrapped cause to determine if it is an encoding or writer-lifecycle error.
  2. Do not reuse or close the request body before the send completes; let the client own body lifetime.
  3. Sanitize formData values (strip control bytes) if they originate from untrusted input.
Defensive patterns

Strategy: validation

Try / catch

if err := c.Post(url, req); err != nil && strings.Contains(err.Error(), "write formdata") {
    log.Printf("multipart field write failed: %v", err)
}

Prevention

When it happens

Trigger: A formData value containing characters the multipart writer cannot encode; the underlying BodyWriter was closed or errored before fields are written; a pipe writer whose read end is gone.

Common situations: Calling req.formData.Add with a value that is not a valid string for the writer; reusing a Request whose RawRequest body was already consumed/closed; concurrent writes to the same body.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/03744574c21f851c. Report an issue: GitHub.

Appendix: source

Thrown at client/hooks.go:267

	if err := mw.Close(); err != nil {
		return fmt.Errorf("failed to close multipart writer: %w", err)
	}

	return nil
}

// writeMultipartBody writes the form fields and files of req to mw.
func writeMultipartBody(mw *multipart.Writer, req *Request) error {
	// Add form data.
	var err error
	for key, value := range req.formData.All() {
		err = mw.WriteField(utils.UnsafeString(key), utils.UnsafeString(value))
		if err != nil {
			break
		}
	}
	if err != nil {
		return fmt.Errorf("write formdata error: %w", err)
	}

	// Add files.
	fileBuf, ok := fileBufPool.Get().(*[]byte)
	if !ok {
		return errSyncPoolBuffer
	}

	defer fileBufPool.Put(fileBuf)

	for i, f := range req.files {
		if f.name == "" && f.path == "" {
			return ErrFileNoName
		}

		// Set the file name if not provided.
		if f.name == "" && f.path != "" {
			f.path = filepath.Clean(f.path)

View on GitHub (pinned to a105acad6c)