labstack/echo · error
binding to multipart.FileHeader struct is not supported, use
Error message
binding to multipart.FileHeader struct is not supported, use pointer to struct
What it means
Returned by isFieldMultipartFile when a struct field used for multipart file binding is of type multipart.FileHeader by value. Echo can only bind files to *multipart.FileHeader, []multipart.FileHeader, or []*multipart.FileHeader because with a value-type FileHeader there is no way to distinguish 'no file uploaded' from 'a file uploaded' — a zero-value FileHeader is indistinguishable from a real one. The pointer/slice forms allow a nil check.
Source
Thrown at bind.go:512
}
var (
// NOT supported by bind as you can NOT check easily empty struct being actual file or not
multipartFileHeaderType = reflect.TypeFor[multipart.FileHeader]()
// supported by bind as you can check by nil value if file existed or not
multipartFileHeaderPointerType = reflect.TypeFor[*multipart.FileHeader]()
multipartFileHeaderSliceType = reflect.TypeFor[[]multipart.FileHeader]()
multipartFileHeaderPointerSliceType = reflect.TypeFor[[]*multipart.FileHeader]()
)
func isFieldMultipartFile(field reflect.Type) (bool, error) {
switch field {
case multipartFileHeaderPointerType,
multipartFileHeaderSliceType,
multipartFileHeaderPointerSliceType:
return true, nil
case multipartFileHeaderType:
return true, errors.New("binding to multipart.FileHeader struct is not supported, use pointer to struct")
default:
return false, nil
}
}
func setMultipartFileHeaderTypes(structField reflect.Value, inputFieldName string, files map[string][]*multipart.FileHeader) bool {
fileHeaders := files[inputFieldName]
if len(fileHeaders) == 0 {
return false
}
result := true
switch structField.Type() {
case multipartFileHeaderPointerSliceType:
structField.Set(reflect.ValueOf(fileHeaders))
case multipartFileHeaderSliceType:
headers := make([]multipart.FileHeader, len(fileHeaders))
for i, fileHeader := range fileHeaders {View on GitHub (pinned to 05489dc173)
Solutions
- Change the field type to *multipart.FileHeader
- For multiple files use []*multipart.FileHeader or []multipart.FileHeader
- Alternatively retrieve the file directly with c.FormFile("file") which returns *multipart.FileHeader
Example fix
// before
type UploadForm struct {
File multipart.FileHeader `form:"file"`
}
// after
type UploadForm struct {
File *multipart.FileHeader `form:"file"`
} Defensive patterns
Strategy: type-guard
Type guard
// Ensure multipart file fields use pointer types
func checkFileHeaderFields(rt reflect.Type) error {
fhType := reflect.TypeFor[multipart.FileHeader]()
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
if f.Type == fhType {
return fmt.Errorf("field %s: use *multipart.FileHeader, not multipart.FileHeader", f.Name)
}
}
return nil
} Try / catch
if err := c.Bind(&req); err != nil {
if strings.Contains(err.Error(), "use pointer to struct") {
return echo.NewHTTPError(http.StatusBadRequest, "file field must use pointer type")
}
return err
} Prevention
- Always use *multipart.FileHeader for single-file struct fields
- Use []*multipart.FileHeader for multiple files
- Alternatively call c.FormFile(name) directly instead of binding
When it happens
Trigger: Defining type UploadForm struct{ File multipart.FileHeader `form:"file"` } and submitting a multipart/form-data request to a handler that calls c.Bind(&UploadForm{}).
Common situations: Following an outdated tutorial using multipart.FileHeader by value. Code generators producing non-pointer FileHeader fields.
Related errors
- binding element must be a struct
- query/param/form tags are not allowed with anonymous struct
- unknown type
- %s: %w
- failed to parse form value, key: %s, err: %w
AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04).
Data as JSON: /data/errors/5b4b44cbe2574851.json.
Report an issue: GitHub.