wavetermdev/waveterm · error

cannot convert %T to %s (key %s) error: %v

Error message

cannot convert %T to %s (key %s) error: %v

What it means

For map[string]waveobj.WaveObj arguments, each map value that passes the object check is decoded with waveobj.FromJsonMap. If decoding fails for any value (missing otype/oid, unknown otype, invalid fields), the whole call fails with this error, which names the failing key and wraps the underlying FromJsonMap error.

Source

Thrown at pkg/service/service.go:162

				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)
		jsonSlice := make([]map[string]any, len(nativeSlice))
		for idx, elem := range nativeSlice {
			elemMap, err := waveobj.ToJsonMap(elem)
			if err != nil {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Read the wrapped inner error and fix the WaveObj stored under the reported key (usually missing/invalid otype or oid).
  2. Ensure every map value carries valid "otype" and "oid" for a registered WaveObj type.
  3. Synchronize client and server versions so otype names and field schemas match.
  4. Build payloads with the SDK serialization helpers (ToJsonMap) instead of hand-assembling maps.

Example fix

// before
callService("objservice", "SetObjects", { "main": { "otype": "tab" } }) // missing oid
// after
callService("objservice", "SetObjects", { "main": { "otype": "tab", "oid": "xyz789", "meta": {} } })
Defensive patterns

Strategy: validation

Validate before calling

for (const [k, v] of Object.entries(arg)) { if (typeof v?.otype !== 'string' || typeof v?.oid !== 'string') throw new Error('map value at key ' + k + ' missing valid otype/oid'); }

Type guard

function isValidWaveObj(v) { return v && typeof v.otype === 'string' && typeof v.oid === 'string'; }

Try / catch

try { return await callService(svc, method, arg); } catch (e) { const m = String(e).match(/key (\S+)\) error: (.*)$/); if (m) { console.error('WaveObj at key ' + m[1] + ' failed decode: ' + m[2]); } throw e; }

Prevention

When it happens

Trigger: An RPC call with a WaveObj map argument where the value at some key is an object but malformed: absent "otype"/"oid", an otype the server doesn't know, or fields failing otype-specific validation.

Common situations: Partially constructed objects placed into maps; an otype introduced in a newer client unknown to an older backend; field renames after a schema migration leaving payloads invalid.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/8655da31aee82606. Report an issue: GitHub.