wavetermdev/waveterm · error
cannot convert %T to %s (key %s is not a map, is %T)
Error message
cannot convert %T to %s (key %s is not a map, is %T)
What it means
For map[string]waveobj.WaveObj arguments, every value in the JSON map must itself be a JSON object decodable as a WaveObj. This error identifies the failing key and the offending value's Go type, e.g. when a map value is a string, number, or nested array instead of a serialized WaveObj.
Source
Thrown at pkg/service/service.go:158
return nil, fmt.Errorf("cannot convert %T to %s (idx %d is not a map, is %T)", jsonArg, waveObjSliceRType, idx, elem)
}
nativeObj, err := waveobj.FromJsonMap(elemMap)
if err != nil {
return nil, fmt.Errorf("cannot convert %T to %s (idx %d) error: %v", jsonArg, waveObjSliceRType, idx, err)
}
nativeSlice[idx] = nativeObj
}
return nativeSlice, nil
} else if argType == waveObjMapRType {
if jsonType.Kind() != reflect.Map {
return nil, fmt.Errorf("cannot convert %T to %s", jsonArg, argType)
}
mapArg := jsonArg.(map[string]any)
nativeMap := make(map[string]waveobj.WaveObj)
for key, elem := range mapArg {
elemMap, ok := elem.(map[string]any)
if !ok {
return nil, fmt.Errorf("cannot convert %T to %s (key %s is not a map, is %T)", jsonArg, waveObjMapRType, key, elem)
}
nativeObj, err := waveobj.FromJsonMap(elemMap)
if err != nil {
return nil, fmt.Errorf("cannot convert %T to %s (key %s) error: %v", jsonArg, waveObjMapRType, key, err)
}
nativeMap[key] = nativeObj
}
return nativeMap, nil
} else {
return nil, fmt.Errorf("invalid special wave argument type %s", argType)
}
}
func convertSpecialForReturn(argType reflect.Type, nativeArg any) (any, error) {
if argType == waveObjRType {
return waveobj.ToJsonMap(nativeArg.(waveobj.WaveObj))
} else if argType == waveObjSliceRType {
nativeSlice := nativeArg.([]waveobj.WaveObj)View on GitHub (pinned to a4447c1563)
Solutions
- Replace the value at the reported key with a full serialized WaveObj object.
- Resolve any orefs/IDs in the map to their full WaveObj JSON before the call.
- Validate every map value is a plain object client-side before invoking.
- Check for version skew between the caller and the service method's expected schema.
Example fix
// before
callService("objservice", "SetObjects", { "main": "block:default:abc" })
// after
callService("objservice", "SetObjects", { "main": await rpcGetWaveObjJson("block:default:abc") }) Defensive patterns
Strategy: validation
Validate before calling
for (const [k, v] of Object.entries(arg)) { if (!v || typeof v !== 'object' || Array.isArray(v)) throw new Error('map value at key ' + k + ' must be a serialized WaveObj object'); } Type guard
const isWaveObjMapValue = (v) => typeof v === 'object' && v !== null && !Array.isArray(v) && typeof v.otype === 'string';
Try / catch
try { return await callService(svc, method, arg); } catch (e) { const m = String(e).match(/key (\S+) is not a map, is (\S+)/); if (m) { console.error('bad WaveObj map value at key', m[1], 'type', m[2]); } throw e; } Prevention
- Resolve every map value to a full WaveObj object, never a string/ID.
- Validate all map values are plain objects before sending.
- Keep map-typed endpoints free of legacy ID-map payloads.
- Surface per-key conversion failures in client logs.
When it happens
Trigger: An RPC call with a WaveObj map argument where at least one value is not an object — commonly map values that are oref strings, object IDs, or booleans.
Common situations: Clients sending {"key": "oref-string"} or {"key": "oid"} maps instead of full object payloads; migrating an endpoint from ID-maps to object-maps while old callers persist; template or dynamically-built payloads injecting the wrong value type for one key.
Related errors
- cannot convert %T to %s (idx %d is not a map, is %T)
- invalid number type %s
- cannot convert %T to %s
- cannot convert %T to %s (idx %d) error: %v
- cannot convert %T to %s (key %s) error: %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/b9d2f5286504222c.
Report an issue: GitHub.