gin-gonic/gin · error · ErrMultiFileHeaderLenInvalid

unsupported len of array for []*multipart.FileHeader

Error message

unsupported len of array for []*multipart.FileHeader

What it means

ErrMultiFileHeaderLenInvalid is returned by setArrayOfMultipartFormFiles (binding/multipart_form_mapping.go:65) when the destination is a fixed-length array ([N]*multipart.FileHeader or [N]multipart.FileHeader) and the number of uploaded files does not equal N. Unlike slices, arrays cannot be resized, so a mismatch is fatal.

Source

Thrown at binding/multipart_form_mapping.go:23

package binding

import (
	"errors"
	"mime/multipart"
	"net/http"
	"reflect"
)

type multipartRequest http.Request

var _ setter = (*multipartRequest)(nil)

var (
	// ErrMultiFileHeader multipart.FileHeader invalid
	ErrMultiFileHeader = errors.New("unsupported field type for multipart.FileHeader")

	// ErrMultiFileHeaderLenInvalid array for []*multipart.FileHeader len invalid
	ErrMultiFileHeaderLenInvalid = errors.New("unsupported len of array for []*multipart.FileHeader")
)

// TrySet tries to set a value by the multipart request with the binding a form file
func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (bool, error) {
	if files := r.MultipartForm.File[key]; len(files) != 0 {
		return setByMultipartFormFile(value, field, files)
	}

	return setByForm(value, field, r.MultipartForm.Value, key, opt)
}

func setByMultipartFormFile(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSet bool, err error) {
	switch value.Kind() {
	case reflect.Ptr:
		switch value.Interface().(type) {
		case *multipart.FileHeader:
			value.Set(reflect.ValueOf(files[0]))
			return true, nil

View on GitHub (pinned to 34dac209ff)

Solutions

  1. Switch the field to []*multipart.FileHeader so it accepts any count, then validate the length in the handler.
  2. Keep the fixed array but enforce the expected count client-side and validate len(r.Filename) before binding.
  3. If exactly N files are mandatory, reject the request with 400 when the file count differs rather than relying on the bind error.

Example fix

// before
type Form struct {
    Files [2]*multipart.FileHeader `form:"files"`
}
// after
type Form struct {
    Files []*multipart.FileHeader `form:"files"`
}
// then: if len(form.Files) != 2 { c.AbortWithStatus(400) }
Defensive patterns

Strategy: validation

Validate before calling

if _, fh := c.MultipartForm.File["files"]; len(fh) != N {
    c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("exactly %d files required", N)})
    return
}

Try / catch

if err := c.ShouldBind(&form); err != nil {
    if errors.Is(err, binding.ErrMultiFileHeaderLenInvalid) {
        c.AbortWithStatus(http.StatusBadRequest) // wrong file count for fixed array
        return
    }
}

Prevention

When it happens

Trigger: Binding a multipart upload into a struct field typed [3]*multipart.FileHeader but the client sends 2 or 4 files under that field name; using a fixed array when the client can send a variable number of files.

Common situations: Hard-coding array length to a contract (e.g. "exactly two avatar variants") and a client sending a different count; copy-paste from a struct where N used to match.

Related errors


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/a80226f57b796281.json. Report an issue: GitHub.