{"record":{"id":"aaab443a30358421","repo":"jmoiron/sqlx","slug":"sqlx-bindnamedmapper-unsupported-map-type-t","errorCode":null,"errorMessage":"sqlx.bindNamedMapper: unsupported map type: %T","messagePattern":"sqlx\\.bindNamedMapper: unsupported map type: %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"named.go","lineNumber":428,"sourceCode":"func BindNamed(bindType int, query string, arg interface{}) (string, []interface{}, error) {\n\treturn bindNamedMapper(bindType, query, arg, mapper())\n}\n\n// Named takes a query using named parameters and an argument and\n// returns a new query with a list of args that can be executed by\n// a database.  The return value uses the `?` bindvar.\nfunc Named(query string, arg interface{}) (string, []interface{}, error) {\n\treturn bindNamedMapper(QUESTION, query, arg, mapper())\n}\n\nfunc bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) {\n\tt := reflect.TypeOf(arg)\n\tk := t.Kind()\n\tswitch {\n\tcase k == reflect.Map && t.Key().Kind() == reflect.String:\n\t\tm, ok := convertMapStringInterface(arg)\n\t\tif !ok {\n\t\t\treturn \"\", nil, fmt.Errorf(\"sqlx.bindNamedMapper: unsupported map type: %T\", arg)\n\t\t}\n\t\treturn bindMap(bindType, query, m)\n\tcase k == reflect.Array || k == reflect.Slice:\n\t\treturn bindArray(bindType, query, arg, m)\n\tdefault:\n\t\treturn bindStruct(bindType, query, arg, m)\n\t}\n}\n\n// NamedQuery binds a named query and then runs Query on the result using the\n// provided Ext (sqlx.Tx, sqlx.Db).  It works with both structs and with\n// map[string]interface{} types.\nfunc NamedQuery(e Ext, query string, arg interface{}) (*Rows, error) {\n\tq, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn e.Queryx(q, args...)","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/jmoiron/sqlx/blob/41dac167fdad5e3fd81d66cafba0951dc6823a30/named.go#L410-L446","documentation":"bindNamedMapper dispatches on the reflect.Kind of the argument: string-keyed maps go to bindMap, arrays/slices to bindArray, everything else to bindStruct. If the argument is a map whose key type is not string AND cannot be converted to map[string]interface{} (convertMapStringInterface fails), sqlx cannot bind it and reports the unsupported type. Non-string map keys have no defined named-parameter semantics.","triggerScenarios":"Passing a map with non-string keys (e.g. map[int]interface{}, map[CustomKey]T, or map with non-basic key type) to BindNamed/Named/NamedExec/NamedQuery (and their Context variants).","commonSituations":"Using map[int]string lookup tables as bind args; map keys defined as named string types wrapped oddly or maps the conversion helper rejects (e.g. map[interface{}]interface{} from YAML); refactored code passing a struct map with custom key struct types.","solutions":["Convert the map to map[string]interface{} (stringify keys) before binding.","Use a struct argument instead so bindStruct/reflectx handles field mapping.","For slices/arrays of values, pass them as the array/slice branch expects.","If using custom key types that are ~string, convert explicitly: m2 := make(map[string]interface{}, len(m))."],"exampleFix":"// before\nargs := map[int]interface{}{1: \"a\"}\ndb.NamedExec(q, args) // unsupported map type\n// after\nargs := map[string]interface{}{\"1\": \"a\"}\ndb.NamedExec(q, args)","handlingStrategy":"validation","validationCode":"func bindableMap(arg interface{}) error {\n\tt := reflect.TypeOf(arg)\n\tif t == nil || t.Kind() != reflect.Map {\n\t\treturn nil // struct/slice handled elsewhere\n\t}\n\tif t.Key().Kind() != reflect.String {\n\t\treturn fmt.Errorf(\"map key %s not string; convert to map[string]interface{}\", t.Key())\n\t}\n\treturn nil\n}","typeGuard":"func isStringKeyedMap(v interface{}) bool {\n\tt := reflect.TypeOf(v)\n\treturn t != nil && t.Kind() == reflect.Map && t.Key().Kind() == reflect.String\n}","tryCatchPattern":"q, args, err := db.BindNamed(query, arg)\nif err != nil && strings.Contains(err.Error(), \"unsupported map type\") {\n\t// convert arg to map[string]interface{} and retry\n\treturn err\n}","preventionTips":["Always pass map[string]interface{} (or msi) for map-based named binding.","Stringify custom/named key types before binding.","Prefer struct args for typed binding; use maps only for dynamic keys.","Add a pre-bind validation helper in your DAO layer."],"tags":["sql","named-parameters","map","reflection","bind"],"backgroundTag":"unsupported-bind-type","analyzedSha":"41dac167fdad5e3fd81d66cafba0951dc6823a30","analyzedAt":"2026-09-03T06:10:20.382Z","contentChangedAt":"2026-09-03T06:10:20.382Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}