semaphoreui/semaphore · error
expected map for field
Error message
expected map for field %s but got %T
What it means
For map-typed struct fields, the assigned value must itself be a Go map. If the value under the matching JSON key is any other kind (string, int, slice, bool), this error is returned. Unlike the struct-field case, a JSON-array-style string is not parsed here — the value must already be a map.
Solutions
- Supply a real map in the source: map[string]any{"host": "localhost"}.
- If the value is a JSON object string, json.Unmarshal it into map[string]any before assignment.
- Verify the config key and struct field type agree — change one so the shapes match.
- For env-sourced maps, parse key=value pairs into a map yourself before calling AssignMapToStruct.
Example fix
// before
m := map[string]any{"db": "host=localhost"} // field is map[string]any
// after
m := map[string]any{"db": map[string]any{"host": "localhost"}} Defensive patterns
Strategy: type-guard
Validate before calling
if v, ok := m["db"]; ok {
if _, isMap := v.(map[string]any); !isMap {
return fmt.Errorf("db must be an object, got %T", v)
}
} Type guard
func isMapValue(v any) bool {
rv := reflect.ValueOf(v)
return rv.Kind() == reflect.Map
} Try / catch
if err := util.AssignMapToStruct(m, &cfg); err != nil {
if strings.Contains(err.Error(), "expected map for field") {
log.Fatalf("map field requires object value: %v", err)
}
} Prevention
- Supply nested config as objects, not delimited strings or lists.
- If values arrive as JSON object strings, unmarshal to map[string]any first.
- Sync flattened env-var config with the map-shaped struct fields explicitly.
When it happens
Trigger: Assigning m["db"] = "host=localhost" (a string) or a slice to a field of type map[string]X via AssignMapToStruct.
Common situations: Env-var-driven config where a map was flattened to a delimited string; config schema changed a field from scalar/slice to map; hand-built maps where the wrong key received a scalar.
Related errors
- cannot assign value of type
- cannot assign value of type %T to field
- expected slice or json array string for field
- expected slice for field
- cannot assign element of type %T to slice element of type
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/aa69e477af9f809b.
Report an issue: GitHub.
Appendix: source
Thrown at util/config.go:1253
return fmt.Errorf("cannot assign element of type %s to slice element of type %s", srcElemVal.Type(), fieldElemType)
}
dstElem = reflect.ValueOf(newVal)
}
}
newSlice = reflect.Append(newSlice, dstElem)
}
fieldValue.Set(newSlice)
case reflect.Map:
if fieldValue.IsNil() {
mapValue := reflect.MakeMap(fieldValue.Type())
fieldValue.Set(mapValue)
}
// Handle map
if val.Kind() != reflect.Map {
return fmt.Errorf("expected map for field %s but got %T", field.Name, value)
}
for _, key := range val.MapKeys() {
mapElemValue := val.MapIndex(key)
mapElemType := fieldValue.Type().Elem()
srcVal := fieldValue.MapIndex(key)
var mapElem reflect.Value
if srcVal.IsValid() {
mapElem = cloneStruct(srcVal)
} else {
mapElem = reflect.New(mapElemType).Elem()
}
if mapElemType.Kind() == reflect.Struct {
if err := assignMapToStructRecursive(mapElemValue.Interface().(map[string]any), mapElem); err != nil {
return err
}View on GitHub (pinned to 1774ccb71a)