{"id":"e36780b56ddb9ada","repo":"gin-gonic/gin","slug":"can-not-convert-to-map-slices-of-strings","errorCode":null,"errorMessage":"can not convert to map slices of strings","messagePattern":"can not convert to map slices of strings","errorType":"validation","errorClass":"ErrConvertMapStringSlice","httpStatus":400,"severity":"error","filePath":"binding/form_mapping.go","lineNumber":26,"sourceCode":"\t\"encoding\"\n\t\"errors\"\n\t\"fmt\"\n\t\"maps\"\n\t\"mime/multipart\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/gin-gonic/gin/codec/json\"\n\t\"github.com/gin-gonic/gin/internal/bytesconv\"\n)\n\nvar (\n\terrUnknownType = errors.New(\"unknown type\")\n\n\t// ErrConvertMapStringSlice can not convert to map[string][]string\n\tErrConvertMapStringSlice = errors.New(\"can not convert to map slices of strings\")\n\n\t// ErrConvertToMapString can not convert to map[string]string\n\tErrConvertToMapString = errors.New(\"can not convert to map of strings\")\n)\n\nfunc mapURI(ptr any, m map[string][]string) error {\n\treturn mapFormByTag(ptr, m, \"uri\")\n}\n\nfunc mapForm(ptr any, form map[string][]string) error {\n\treturn mapFormByTag(ptr, form, \"form\")\n}\n\nfunc MapFormWithTag(ptr any, form map[string][]string, tag string) error {\n\treturn mapFormByTag(ptr, form, tag)\n}\n\nvar emptyField = reflect.StructField{}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/gin-gonic/gin/blob/34dac209ffb6ef85cc78c5d217bbb7ad001d68fd/binding/form_mapping.go#L8-L44","documentation":"ErrConvertMapStringSlice is returned by setFormMap (binding/form_mapping.go:534) when the binding target is a map whose element kind is Slice but the concrete value is not exactly map[string][]string. Gin only knows how to copy form values into the canonical map[string][]string shape.","triggerScenarios":"Binding a request into a variable typed map[string][]<non-string> (e.g. map[string][]int, map[string][]MyType) and then calling c.ShouldBind / MapFormWithTag.","commonSituations":"Trying to reuse a typed map (map[string][]int) as the bind target instead of a struct; passing a custom map alias type that does not satisfy the concrete map[string][]string assertion.","solutions":["Declare the bind target as map[string][]string (the only slice-map shape Gin supports) and convert values yourself afterwards.","Prefer a struct with typed slice fields (e.g. IDs []int `form:\"ids\"`) so Gin's per-element setWithProperType does the conversion.","If you need a custom map type, build a map[string][]string, call MapFormWithTag into it, then copy into your custom map."],"exampleFix":"// before\nm := map[string][]int{}\nc.ShouldBindWith(&m, binding.Query)\n// after\nraw := map[string][]string{}\nc.ShouldBindWith(&raw, binding.Query)\n// then convert raw into your typed map","handlingStrategy":"type-guard","validationCode":"var target any = map[string][]int{}\nif reflect.TypeOf(target).Kind() == reflect.Map {\n    elem := reflect.TypeOf(target).Elem()\n    if elem.Kind() == reflect.Slice && elem != reflect.TypeOf([]string{}).Elem() {\n        // will fail; switch to map[string][]string or use a struct\n    }\n}","typeGuard":"func isFormMapStringSlice(v any) bool {\n    _, ok := v.(map[string][]string)\n    return ok\n}","tryCatchPattern":"if err := c.ShouldBindWith(&m, binding.Form); err != nil {\n    if errors.Is(err, binding.ErrConvertMapStringSlice) {\n        // target was a non-canonical slice-map; bind into map[string][]string and convert\n    }\n}","preventionTips":["Prefer structs with typed slice fields over typed maps for binding.","If you must use a map, declare it as map[string][]string (or map[string]string).","Document the canonical map shapes in your handler signatures."],"tags":["binding","form","map","go"],"analyzedSha":"34dac209ffb6ef85cc78c5d217bbb7ad001d68fd","analyzedAt":"2026-08-04T21:26:18.438Z","schemaVersion":2}