{"record":{"id":"b925fd2d7bab8ec7","repo":"wavetermdev/waveterm","slug":"invalid-special-wave-argument-type-s","errorCode":null,"errorMessage":"invalid special wave argument type %s","messagePattern":"invalid special wave argument type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/service.go","lineNumber":168,"sourceCode":"\t\tif jsonType.Kind() != reflect.Map {\n\t\t\treturn nil, fmt.Errorf(\"cannot convert %T to %s\", jsonArg, argType)\n\t\t}\n\t\tmapArg := jsonArg.(map[string]any)\n\t\tnativeMap := make(map[string]waveobj.WaveObj)\n\t\tfor key, elem := range mapArg {\n\t\t\telemMap, ok := elem.(map[string]any)\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot convert %T to %s (key %s is not a map, is %T)\", jsonArg, waveObjMapRType, key, elem)\n\t\t\t}\n\t\t\tnativeObj, err := waveobj.FromJsonMap(elemMap)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"cannot convert %T to %s (key %s) error: %v\", jsonArg, waveObjMapRType, key, err)\n\t\t\t}\n\t\t\tnativeMap[key] = nativeObj\n\t\t}\n\t\treturn nativeMap, nil\n\t} else {\n\t\treturn nil, fmt.Errorf(\"invalid special wave argument type %s\", argType)\n\t}\n}\n\nfunc convertSpecialForReturn(argType reflect.Type, nativeArg any) (any, error) {\n\tif argType == waveObjRType {\n\t\treturn waveobj.ToJsonMap(nativeArg.(waveobj.WaveObj))\n\t} else if argType == waveObjSliceRType {\n\t\tnativeSlice := nativeArg.([]waveobj.WaveObj)\n\t\tjsonSlice := make([]map[string]any, len(nativeSlice))\n\t\tfor idx, elem := range nativeSlice {\n\t\t\telemMap, err := waveobj.ToJsonMap(elem)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tjsonSlice[idx] = elemMap\n\t\t}\n\t\treturn jsonSlice, nil\n\t} else if argType == waveObjMapRType {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/service.go#L150-L186","documentation":"convertSpecial only knows how to decode the registered special argument types (waveobj.ORef, webcmd.WSCommand, waveobj.WaveObj, []waveobj.WaveObj, map[string]waveobj.WaveObj). If isSpecialWaveArgType/convertSpecial is reached with a reflect.Type outside that set, it reports the unsupported type. This indicates an internal inconsistency: a type was classified as special but has no decoding branch.","triggerScenarios":"Calling CallService on a method whose parameter type was newly added to isSpecialWaveArgType without a matching branch in convertSpecial, or a refactor that changed/renamed the special RTypes (orefRType, wsCommandRType, waveObjRType, waveObjSliceRType, waveObjMapRType).","commonSituations":"A developer adds a new special argument type to the RPC layer but forgets the convertSpecial branch; merge conflicts that drop a branch; type alias changes making a comparison fail.","solutions":["Add an explicit branch in convertSpecial (and convertSpecialForReturn) for the new special reflect.Type.","Audit isSpecialWaveArgType so it only returns true for types convertSpecial handles.","Reconcile merge changes to the RType variables (orefRType, waveObjRType, etc.) and their comparisons.","As a caller, avoid declaring service-method params of custom types; use the supported special types or plain JSON types."],"exampleFix":"// before (convertSpecial)\n} else {\n    return nil, fmt.Errorf(\"invalid special wave argument type %s\", argType)\n}\n// after\n} else if argType == myNewRType {\n    return decodeMyNewType(jsonArg)\n} else {\n    return nil, fmt.Errorf(\"invalid special wave argument type %s\", argType)\n}","handlingStrategy":"fallback","validationCode":"const SUPPORTED_SPECIALS = ['waveobj.ORef', 'webcmd.WSCommand', 'waveobj.WaveObj', '[]waveobj.WaveObj', 'map[string]waveobj.WaveObj'];\n// server-side guard when adding types: if isSpecialWaveArgType(t) && !handledByConvertSpecial(t) { panic('unhandled special type: ' + t) }","typeGuard":null,"tryCatchPattern":"err := convertSpecial(argType, jsonArg)\nif err != nil { log.Printf(\"special arg conversion failed for %s: %v\", argType, err); return webErrorRtn(err) }","preventionTips":["Extend convertSpecial and convertSpecialForReturn together with isSpecialWaveArgType.","Add a unit test asserting every special type has a decode branch.","Avoid ad-hoc custom types in service-method signatures.","Review RType comparisons after refactors/merges."],"tags":["rpc","reflection","unsupported-type","internal"],"backgroundTag":"unsupported-type","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}