{"record":{"id":"8775b49c05e55b71","repo":"wavetermdev/waveterm","slug":"invalid-pointer-type-s","errorCode":null,"errorMessage":"invalid pointer type %s","messagePattern":"invalid pointer type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/service.go","lineNumber":254,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"cannot convert %T to %s\", jsonArg, argType)\n\t\t}\n\t\treturn convertComplex(argType, jsonArg)\n\n\tcase reflect.Slice:\n\t\tif jsonType.Kind() != reflect.Slice {\n\t\t\treturn nil, fmt.Errorf(\"cannot convert %T to %s\", jsonArg, argType)\n\t\t}\n\t\treturn convertComplex(argType, jsonArg)\n\n\tcase reflect.Struct:\n\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\treturn convertComplex(argType, jsonArg)\n\n\tcase reflect.Ptr:\n\t\tif argType.Elem().Kind() != reflect.Struct {\n\t\t\treturn nil, fmt.Errorf(\"invalid pointer type %s\", argType)\n\t\t}\n\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\treturn convertComplex(argType, jsonArg)\n\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid argument type %s\", argType)\n\t}\n}\n\nfunc isNilable(val reflect.Value) bool {\n\tswitch val.Kind() {\n\tcase reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface, reflect.Chan, reflect.Func:\n\t\treturn true\n\t}\n\treturn false\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/service.go#L236-L272","documentation":"Thrown when a service method parameter is a pointer whose element kind is not Struct (e.g. *string, *int, *map). The RPC bridge only supports pointer-to-struct parameters (populated from JSON objects); other pointer types are unconvertible from JSON and are rejected before the JSON shape is even examined.","triggerScenarios":"A registered service method declares *string, *int, *[]string, or another non-struct pointer parameter, and a client calls it via CallService. The error fires regardless of what JSON value was passed.","commonSituations":"Service authors using pointer types for optional scalars (a common Go idiom) without realizing the RPC layer can't build them; refactoring signatures to add optional params as pointers.","solutions":["Change the parameter to a plain value type (string, int) or a pointer-to-struct; handle optionality inside the method.","Wrap the optional scalar in a struct (e.g. type Opt struct{ Value string }) and accept *Opt.","If nil-vs-zero matters, accept an interface/special arg type supported by the bridge or split into two methods."],"exampleFix":"// before\nfunc (s *Svc) SetName(name *string) error\n\n// after\ntype SetNameOpts struct { Name string }\nfunc (s *Svc) SetName(opts SetNameOpts) error { ... }","handlingStrategy":"validation","validationCode":"// check the Go signature before calling: only *Struct pointer params are supported\nif (paramKind === 'ptr' && pointedKind !== 'struct') throw new Error('unsupported *T param; wrap in struct');","typeGuard":null,"tryCatchPattern":"try {\n  const rtn = await callService(svc, method, args);\n  if (rtn.error?.includes('invalid pointer type')) throw new Error('method signature uses unsupported pointer type');\n} catch (e) { /* redesign call: pass value type or *struct wrapper */ }","preventionTips":["Avoid *string/*int optional-scalar params in RPC-exposed methods; use structs or plain values.","Keep RPC service signatures limited to bridge-supported kinds.","Add a unit test that exercises each service method via CallService to surface unsupported types."],"tags":["rpc","pointer","unsupported-type","reflection"],"backgroundTag":"rpc-unsupported-parameter-type","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}