{"record":{"id":"504883bb783ba28a","repo":"semaphoreui/semaphore","slug":"expected-map-for-nested-struct-field-s-but-got-t","errorCode":null,"errorMessage":"expected map for nested struct field %s but got %T","messagePattern":"expected map for nested struct field (.+?) but got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/config.go","lineNumber":1166,"sourceCode":"\n\t\tjsonTag := field.Tag.Get(\"json\")\n\t\tif jsonTag == \"\" {\n\t\t\tjsonTag = field.Name\n\t\t} else {\n\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","sourceCodeStart":1148,"sourceCodeEnd":1184,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/util/config.go#L1148-L1184","documentation":"Returned by the reflective config-decoding helper in util/config.go when it walks into a nested struct field (by Go field name in the message) and the corresponding value in the source map is not itself a map. The %T shows the actual JSON type found (string, float64, []interface{}, bool). It is a type guard for structurally invalid config: nested sections must decode from JSON objects; any scalar or array where a section object is expected triggers this error.","triggerScenarios":"Thrown at util/config.go:1166 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fix the config file/environment mapping so the named section is a JSON/YAML object with the nested field keys inside it","Move mistyped keys that belong one level deeper under the proper parent section","Check the %T hint — a string or number where the object is expected usually means a missing nesting level or a stray '=' style flat key","Compare the section against config.schema.yaml to see the expected nested structure"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}