gin-gonic/gin · error · ErrConvertToMapString
can not convert to map of strings
Error message
can not convert to map of strings
What it means
ErrConvertToMapString is returned by setFormMap (binding/form_mapping.go:543) when the bind target is a string-keyed map whose element kind is not Slice, but the concrete value fails the map[string]string type assertion. Gin can only write the last form value per key into map[string]string.
Source
Thrown at binding/form_mapping.go:29
"maps"
"mime/multipart"
"reflect"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin/codec/json"
"github.com/gin-gonic/gin/internal/bytesconv"
)
var (
errUnknownType = errors.New("unknown type")
// ErrConvertMapStringSlice can not convert to map[string][]string
ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings")
// ErrConvertToMapString can not convert to map[string]string
ErrConvertToMapString = errors.New("can not convert to map of strings")
)
func mapURI(ptr any, m map[string][]string) error {
return mapFormByTag(ptr, m, "uri")
}
func mapForm(ptr any, form map[string][]string) error {
return mapFormByTag(ptr, form, "form")
}
func MapFormWithTag(ptr any, form map[string][]string, tag string) error {
return mapFormByTag(ptr, form, tag)
}
var emptyField = reflect.StructField{}
func mapFormByTag(ptr any, form map[string][]string, tag string) error {
// Check if ptr is a mapView on GitHub (pinned to 34dac209ff)
Solutions
- Use a plain map[string]string as the bind target (Gin will pick the last value for each key).
- Switch to a struct with typed fields so the per-field converters run.
- For named/aliased map types, bind into map[string]string first, then copy into your alias.
Example fix
// before
type Params map[string]string
p := Params{}
c.ShouldBindWith(&p, binding.Query)
// after
p := map[string][]string{}
c.ShouldBindWith(&p, binding.Query)
params := Params{}
for k, v := range p { params[k] = v[len(v)-1] } Defensive patterns
Strategy: type-guard
Validate before calling
var target any = Params{}
if reflect.TypeOf(target).Kind() == reflect.Map &&
reflect.TypeOf(target).Elem().Kind() != reflect.Slice &&
reflect.TypeOf(target) != reflect.TypeOf(map[string]string{}) {
// will fail; switch to map[string]string or a struct
} Type guard
func isFormMapString(v any) bool {
_, ok := v.(map[string]string)
return ok
} Try / catch
if err := c.ShouldBindWith(&m, binding.Form); err != nil {
if errors.Is(err, binding.ErrConvertToMapString) {
// typed/aliased string-map; bind into map[string]string then copy
}
} Prevention
- Avoid named map types as bind targets; use the predeclared map[string]string.
- Convert form values to typed maps after binding, not during.
- Add a unit test that binds a sample request into each of your map targets.
When it happens
Trigger: Binding into a map whose value type is a non-string scalar (map[string]int, map[string]bool, map[string]time.Time) or a custom alias of map[string]string.
Common situations: Binding query params into a typed map (map[string]int) expecting automatic conversion; using a named type `type Params map[string]string` whose assertion to the predeclared map[string]string fails.
Related errors
- can not convert to map slices of strings
- unknown type
- %s is not supported in the collection_format. (multi, csv, s
- %q is not valid value for %s
- invalid request
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/704c28c5462c6127.json.
Report an issue: GitHub.