semaphoreui/semaphore · error
cannot assign element of type %T to slice element of type
Error message
cannot assign element of type %T to slice element of type %s
What it means
When filling a slice of structs, each source element must be a map[string]any (to recurse into the struct) or convertible to the element type. If the element is a map of some other type (e.g. map[string]string) this error is returned. It indicates a struct-slice element arrived in a representation the reflector cannot consume.
Solutions
- Convert each element map to map[string]any before assignment.
- Unmarshal the source document with encoding/json into any so nested objects become map[string]any.
- If the element is actually a scalar, either wrap it so it can convert to the struct's element type or fix the field type.
- Write a normalization helper that recursively converts maps to map[string]any and apply it to the whole input map.
Example fix
// before
items := []map[string]string{{"name": "a"}}
m := map[string]any{"items": items} // field is []Item
// after
m := map[string]any{"items": []any{map[string]any{"name": "a"}}} Defensive patterns
Strategy: type-guard
Validate before calling
for _, e := range items.([]any) {
if _, ok := e.(map[string]any); !ok {
return fmt.Errorf("slice elements must be objects (map[string]any)")
}
} Type guard
func isStringAnyMapSlice(v any) bool {
s, ok := v.([]any)
if !ok { return false }
for _, e := range s {
if _, ok := e.(map[string]any); !ok { return false }
}
return true
} Try / catch
if err := util.AssignMapToStruct(m, &cfg); err != nil {
if strings.Contains(err.Error(), "cannot assign element of type") {
log.Fatalf("struct-slice element shape wrong: %v", err)
}
} Prevention
- Use encoding/json for all config decoding so nested objects become map[string]any.
- Avoid YAML/TOML decoders that emit map[interface{}]interface{} without conversion.
- Write one recursive normalization helper and apply it to all external config input.
When it happens
Trigger: Assigning []any{map[string]string{...}} or []map[string]string{...} to a field of type []SomeStruct via AssignMapToStruct.
Common situations: YAML/TOML decoders producing map[interface{}]interface{} or typed maps inside slices; hand-assembled config slices using non-any map types; JSON re-marshaled into typed maps before assignment.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- 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
- expected map for field
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/262456cde694f9c5.
Report an issue: GitHub.
Appendix: source
Thrown at util/config.go:1218
// Build destination slice
newSlice := reflect.MakeSlice(fieldValue.Type(), 0, sourceSlice.Len())
for i := 0; i < sourceSlice.Len(); i++ {
srcElemVal := sourceSlice.Index(i)
// When source is []any, elements come as interface{}, unwrap reflect.Value
if srcElemVal.Kind() == reflect.Interface && !srcElemVal.IsNil() {
srcElemVal = reflect.ValueOf(srcElemVal.Interface())
}
var dstElem reflect.Value
// Prepare destination element
if fieldElemType.Kind() == reflect.Struct {
dstElem = reflect.New(fieldElemType).Elem()
if srcElemVal.Kind() == reflect.Map {
// Expect map[string]any
mIface, ok := srcElemVal.Interface().(map[string]any)
if !ok {
return fmt.Errorf("cannot assign element of type %T to slice element of type %s", srcElemVal.Interface(), fieldElemType)
}
if err := assignMapToStructRecursive(mIface, dstElem); err != nil {
return err
}
} else if srcElemVal.Type().ConvertibleTo(fieldElemType) {
dstElem = srcElemVal.Convert(fieldElemType)
} else {
return fmt.Errorf("cannot assign element of type %s to slice element of type %s", srcElemVal.Type(), fieldElemType)
}
} else {
// Primitive or other kinds
if srcElemVal.Type().ConvertibleTo(fieldElemType) {
dstElem = srcElemVal.Convert(fieldElemType)
} else {
newVal, converted := CastValueToKind(srcElemVal.Interface(), fieldElemType.Kind())
if !converted {
return fmt.Errorf("cannot assign element of type %s to slice element of type %s", srcElemVal.Type(), fieldElemType)
}View on GitHub (pinned to 1774ccb71a)