{"record":{"id":"64f19677f2661803","repo":"wavetermdev/waveterm","slug":"nil-wshrpc-passed-to-wshclient","errorCode":null,"errorMessage":"nil wshrpc passed to wshclient","messagePattern":"nil wshrpc passed to wshclient","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshclient/wshclientutil.go","lineNumber":22,"sourceCode":"package wshclient\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\t\"github.com/wavetermdev/waveterm/pkg/panichandler\"\n\t\"github.com/wavetermdev/waveterm/pkg/util/utilfn\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshrpc\"\n\t\"github.com/wavetermdev/waveterm/pkg/wshutil\"\n)\n\nfunc sendRpcRequestCallHelper[T any](w *wshutil.WshRpc, command string, data interface{}, opts *wshrpc.RpcOpts) (T, error) {\n\tif opts == nil {\n\t\topts = &wshrpc.RpcOpts{}\n\t}\n\tvar respData T\n\tif w == nil {\n\t\treturn respData, errors.New(\"nil wshrpc passed to wshclient\")\n\t}\n\tif opts.NoResponse {\n\t\terr := w.SendCommand(command, data, opts)\n\t\tif err != nil {\n\t\t\treturn respData, err\n\t\t}\n\t\treturn respData, nil\n\t}\n\tresp, err := w.SendRpcRequest(command, data, opts)\n\tif err != nil {\n\t\treturn respData, err\n\t}\n\terr = utilfn.ReUnmarshal(&respData, resp)\n\tif err != nil {\n\t\treturn respData, err\n\t}\n\treturn respData, nil\n}","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshclient/wshclientutil.go#L4-L40","documentation":"The generic wsh client helper sendRpcRequestCallHelper guards against a nil *wshutil.WshRpc: if the provided wshrpc is nil, calling methods on it would panic, so it returns this error instead. All single-response wsh commands (ActivityCommand, AuthenticateCommand, AiSendMessageCommand, etc.) funnel through this helper, so any of them can surface it.","triggerScenarios":"Passing a nil *wshutil.WshRpc to any generated wshclient command function, typically because the client/router was not yet initialized, initialization failed, or a struct field holding the rpc client was left unset (zero value).","commonSituations":"Calling wsh commands before the block/controller wiring finishes; shutdown races where the rpc object was cleared to nil; forgetting to assign the WshRpc field when constructing a controller manually; tests constructing commands without a mock rpc.","solutions":["Ensure the *wshutil.WshRpc is created and assigned (e.g. via the block controller/router setup) before invoking any wshclient commands.","Add a nil check on the rpc reference at your call site and defer or abort the command if nil.","If the rpc may come and go, hold it behind an accessor that returns (rpc, ok) and skip the command when not ready.","In tests, inject a real or mock WshRpc rather than leaving the field zero-valued."],"exampleFix":"// before\nerr := wshclient.AuthenticateCommand(rpc, authData, nil) // rpc may be nil\n// after\nif rpc == nil {\n    return fmt.Errorf(\"cannot authenticate: rpc client not initialized\")\n}\nerr := wshclient.AuthenticateCommand(rpc, authData, nil)","handlingStrategy":"validation","validationCode":"if rpc == nil {\n    return fmt.Errorf(\"wsh rpc client not initialized; cannot send command\")\n}","typeGuard":"func rpcReady(w *wshutil.WshRpc) bool { return w != nil }","tryCatchPattern":"resp, err := wshclient.AuthenticateCommand(rpc, data, nil)\nif err != nil && strings.Contains(err.Error(), \"nil wshrpc passed to wshclient\") {\n    return fmt.Errorf(\"rpc client not initialized: %w\", err)\n}\nif err != nil {\n    return err\n}","preventionTips":["Initialize the WshRpc in the constructor of any controller that issues wsh commands.","Never assign nil to an rpc field during teardown before stopping dependent commands.","Centralize command dispatch in one helper that nil-checks the rpc once.","In tests, always inject a real or mock WshRpc, never the zero value."],"tags":["go","nil-pointer","rpc","initialization-order","wsh"],"backgroundTag":"nil-client-not-initialized","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}