{"record":{"id":"ab5f0cdacdc73463","repo":"semaphoreui/semaphore","slug":"cannot-assign-value-of-type-t-to-field-s-of-type","errorCode":null,"errorMessage":"cannot assign value of type %T to field %s of type %s","messagePattern":"cannot assign value of type %T to field (.+?) of type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/config.go","lineNumber":1171,"sourceCode":"\t\t\tjsonTag = strings.Split(jsonTag, \",\")[0]\n\t\t}\n\n\t\tif value, ok := m[jsonTag]; ok {\n\t\t\tfieldValue := structValue.FieldByName(field.Name)\n\t\t\tif fieldValue.CanSet() {\n\n\t\t\t\tval := reflect.ValueOf(value)\n\n\t\t\t\tswitch fieldValue.Kind() {\n\t\t\t\tcase reflect.Struct:\n\n\t\t\t\t\tif val.Kind() != reflect.Map {\n\t\t\t\t\t\treturn fmt.Errorf(\"expected map for nested struct field %s but got %T\", field.Name, value)\n\t\t\t\t\t}\n\n\t\t\t\t\tmapValue, ok := value.(map[string]any)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn fmt.Errorf(\"cannot assign value of type %T to field %s of type %s\", value, field.Name, field.Type)\n\t\t\t\t\t}\n\t\t\t\t\terr := assignMapToStructRecursive(mapValue, fieldValue)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\tcase reflect.Slice:\n\t\t\t\t\t// Handle slice assignment\n\t\t\t\t\tfieldElemType := fieldValue.Type().Elem()\n\t\t\t\t\tvar sourceSlice reflect.Value\n\t\t\t\t\tif val.Kind() == reflect.Slice || val.Kind() == reflect.Array {\n\t\t\t\t\t\tsourceSlice = val\n\t\t\t\t\t} else if val.Kind() == reflect.String {\n\t\t\t\t\t\t// Try to parse JSON array from string\n\t\t\t\t\t\tstr := val.String()\n\t\t\t\t\t\t// First, try to unmarshal into []any\n\t\t\t\t\t\tvar anyArr []any\n\t\t\t\t\t\tif err := json.Unmarshal([]byte(str), &anyArr); err == nil {\n\t\t\t\t\t\t\tsourceSlice = reflect.ValueOf(anyArr)","sourceCodeStart":1153,"sourceCodeEnd":1189,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1153-L1189","documentation":"assignMapToStructRecursive maps a map[string]any onto a struct via reflection. When a struct field's JSON-matching value passes the 'is a map' check but fails the typed assertion to map[string]any (it is a map with different key/value types, e.g. map[string]string), this error is returned. It signals the value's concrete Go type cannot feed the recursive struct assignment for that field.","triggerScenarios":"Calling util.AssignMapToStruct with a value for a struct-typed field that is a reflect.Map but not a map[string]any — e.g. passing map[string]string{...} or a map[string]int under a key that maps to a nested struct field.","commonSituations":"Building config maps by hand with typed maps instead of map[string]any; loading config from a decoder (e.g. yaml/toml) that produces map[string]interface{} alternatives like map[interface{}]interface{}; JSON that was unmarshaled into a typed map rather than any.","solutions":["Convert the value to map[string]any before calling AssignMapToStruct (copy keys/values into a new map[string]any).","Unmarshal the source JSON into map[string]any (json.Unmarshal into any) instead of a typed map so nested values have the right type.","Normalize decoder output (e.g. convert map[interface{}]interface{} from YAML to map[string]any) before assignment.","If the field should not be a struct, fix the struct definition or the config key so types agree."],"exampleFix":"// before\nm := map[string]any{\"db\": map[string]string{\"host\": \"localhost\"}}\nutil.AssignMapToStruct(m, &cfg)\n// after\nutil.AssignMapToStruct(map[string]any{\n  \"db\": map[string]any{\"host\": \"localhost\"},\n}, &cfg)","handlingStrategy":"type-guard","validationCode":"func isStringAnyMap(v any) bool { _, ok := v.(map[string]any); return ok }\nif !isStringAnyMap(m[\"db\"]) { return fmt.Errorf(\"field db must be map[string]any\") }","typeGuard":"func asStringAnyMap(v any) (map[string]any, bool) {\n  if m, ok := v.(map[string]any); ok {\n    return m, true\n  }\n  return nil, false\n}","tryCatchPattern":"err := util.AssignMapToStruct(m, &cfg)\nif err != nil {\n  var typeErr *fmt.Errorf // Inspect err.Error() for \"cannot assign value of type\"\n  _ = typeErr\n  log.Fatalf(\"config map shape invalid: %v\", err)\n}","preventionTips":["Always build config maps as map[string]any throughout, never typed maps.","Unmarshal source documents with encoding/json into any so nested objects are map[string]any.","Add a normalize step converting any map kinds to map[string]any before assignment."],"tags":["reflection","config","go","type-assertion"],"backgroundTag":"incompatible-source-type","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}