go-kratos/kratos · error
config: merge src must be map[string]interface{}, got %T
Error message
config: merge src must be map[string]interface{}, got %T What it means
The default config merger converts src via convertMap and requires the result to be map[string]interface{}; values that decode to slices, scalars, or other shapes fail this check. The root cause is almost always a config document whose top level is not a mapping (e.g. a YAML list or JSON array).
Source
Thrown at config/merge.go:12
package config
import "fmt"
func defaultMerge(dst, src any) error {
dstMap, ok := dst.(*map[string]any)
if !ok {
return fmt.Errorf("config: merge dst must be *map[string]interface{}, got %T", dst)
}
srcMap, ok := convertMap(src).(map[string]any)
if !ok {
return fmt.Errorf("config: merge src must be map[string]interface{}, got %T", src)
}
if *dstMap == nil {
*dstMap = make(map[string]any, len(srcMap))
}
mergeMap(*dstMap, srcMap)
return nil
}
func mergeMap(dst, src map[string]any) {
for key, srcValue := range src {
if srcMap, ok := srcValue.(map[string]any); ok {
if dstMap, ok := dst[key].(map[string]any); ok {
mergeMap(dstMap, srcMap)
continue
}
}
dst[key] = cloneMergeValue(srcValue)
}View on GitHub (pinned to 668db92c2c)
Solutions
- Edit the config file so its top level is a mapping (YAML map / JSON object)
- Move lists under a named key: items: [ ... ]
- Validate locally before shipping: yaml.Unmarshal(file, &map[string]any) must succeed
Example fix
# before - config.yaml (top-level list)
- name: a
port: 8000
- name: b
port: 8001
# after
services:
- name: a
port: 8000
- name: b
port: 8001 Defensive patterns
Strategy: type-guard
Validate before calling
var probe any
if err := codec.Unmarshal(raw, &probe); err != nil {
return err
}
if _, ok := probe.(map[string]any); !ok {
return fmt.Errorf("config root must be a mapping, got %T", probe)
} Type guard
func isMapConfig(v any) bool {
switch v.(type) {
case map[string]any, map[any]any:
return true
}
return false
} Prevention
- Keep every config file's top level a mapping
- Put lists under a named key, never at the root
- Validate config files by decoding into map[string]any in CI
When it happens
Trigger: A Source returns bytes that decode to a non-map root — YAML starting with a list item, a JSON array, or a bare scalar — so convertMap(src) cannot produce map[string]any during merge.
Common situations: A docker-compose-style YAML fragment reused as config; concatenated YAML documents; a values file that is a single scalar; hand-written JSON arrays at the root.
Related errors
- config: merge dst must be *map[string]interface{}, got %T
- invalid Discovery config nodes:%+v region:%s zone:%s deployE
- unable to parse repo url
- key not found
- path invalid
AI-assisted analysis of go-kratos/kratos@668db92c2c (2026-08-16).
Data as JSON: /api/errors/7df9d5c05782aa70.
Report an issue: GitHub.