siyuan-note/siyuan · error
unsupported multipart field
Error message
unsupported multipart field: %s
What it means
DecodeMultipart only knows how to map file parts (*multipart.FileHeader / slice) and string / *string parts; any struct field of another type hits the default branch and fails with this error. The request struct's field types must be restricted to the supported set, since multipart form values are strings and file headers only.
Solutions
- Change the field type to string (or *string) in the request struct and convert/parse it in the business handler.
- Remove the field from the struct if it is not actually part of the form.
- Handle the raw form via the MultipartFields request type if you need arbitrary access to values.
Example fix
// before
type req struct {
Count int `api:"count"`
}
// after
type req struct {
Count string `api:"count"` // strconv.Atoi in handler
} Defensive patterns
Strategy: type-guard
Validate before calling
// Go: ensure multipart struct fields are only string, *string, *multipart.FileHeader, or []*multipart.FileHeader
for _, f := range reflect.TypeOf(Req{}).Fields() { _ = f } Type guard
func multipartFieldTypeOk(t reflect.Type) bool { return t == reflect.TypeFor[string]() || t == reflect.TypeFor[*string]() || t == reflect.TypeFor[*multipart.FileHeader]() || t == reflect.TypeFor[[]*multipart.FileHeader]() } Try / catch
if err := decode(form); err != nil && strings.Contains(err.Error(), "unsupported multipart field") { log.Fatalf("unsupported field type in request struct: %v", err) } Prevention
- Restrict multipart request struct fields to strings and file headers only.
- Parse numbers/booleans from strings in the business handler.
- Cover each multipart struct with a decode unit test.
When it happens
Trigger: A multipart endpoint's request struct contains a field of an unsupported type, e.g. int, bool, []string, time.Time, or a custom struct, carrying an `api` form tag.
Common situations: Developer adds a numeric or boolean convenience field to an existing multipart request struct without realizing only strings/files are supported; code generation produced a typed field from a schema that assumed JSON bodies.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/da13b456b90ac2b0.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/apicontract/multipart.go:98
value.Field(i).Set(reflect.ValueOf(files[0]))
}
case reflect.TypeFor[string](), reflect.TypeFor[*string]():
values := form.Value[name]
if len(values) == 0 {
if !optional {
return request, fmt.Errorf("Field [%s] is required", name)
}
continue
}
if field.Type.Kind() == reflect.Pointer {
text := reflect.New(field.Type.Elem())
text.Elem().SetString(values[0])
value.Field(i).Set(text)
} else {
value.Field(i).SetString(values[0])
}
default:
return request, fmt.Errorf("unsupported multipart field: %s", name)
}
}
return
}
View on GitHub (pinned to 9f775e8a12)