{"record":{"id":"c33926aaacca5e64","repo":"wavetermdev/waveterm","slug":"invalid-method-s-s","errorCode":null,"errorMessage":"invalid method: %s.%s","messagePattern":"invalid method: (.+?)\\.(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/service/service.go","lineNumber":324,"sourceCode":"\t\trtn.Success = true\n\t}\n\treturn rtn\n}\n\nfunc webErrorRtn(err error) *WebReturnType {\n\treturn &WebReturnType{\n\t\tError: err.Error(),\n\t}\n}\n\nfunc CallService(ctx context.Context, webCall WebCallType) *WebReturnType {\n\tsvcObj := ServiceMap[webCall.Service]\n\tif svcObj == nil {\n\t\treturn webErrorRtn(fmt.Errorf(\"invalid service: %q\", webCall.Service))\n\t}\n\tmethod := reflect.ValueOf(svcObj).MethodByName(webCall.Method)\n\tif !method.IsValid() {\n\t\treturn webErrorRtn(fmt.Errorf(\"invalid method: %s.%s\", webCall.Service, webCall.Method))\n\t}\n\tvar valueArgs []reflect.Value\n\targIdx := 0\n\tfor idx := 0; idx < method.Type().NumIn(); idx++ {\n\t\targType := method.Type().In(idx)\n\t\tif idx == 0 && argType == contextRType {\n\t\t\tvalueArgs = append(valueArgs, reflect.ValueOf(ctx))\n\t\t\tcontinue\n\t\t}\n\t\tif argType == uiContextRType {\n\t\t\tif webCall.UIContext == nil {\n\t\t\t\treturn webErrorRtn(fmt.Errorf(\"missing UIContext for %s.%s\", webCall.Service, webCall.Method))\n\t\t\t}\n\t\t\tvalueArgs = append(valueArgs, reflect.ValueOf(*webCall.UIContext))\n\t\t\tcontinue\n\t\t}\n\t\tif argIdx >= len(webCall.Args) {\n\t\t\treturn webErrorRtn(fmt.Errorf(\"not enough arguments passed %s.%s idx:%d (type %T)\", webCall.Service, webCall.Method, idx, argType))","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/service/service.go#L306-L342","documentation":"CallService resolves frontend RPC calls by looking up the service in ServiceMap and then locating the requested method on it via reflection (MethodByName). This error is returned when the service exists but the method name does not match any exported method on that service object. It is Wave Terminal's guard against calls to RPC methods that do not exist (or are not exported) on the target service.","triggerScenarios":"A frontend wsh/rpc call carries webCall.Service set to a registered service (e.g. \"workspace\") but webCall.Method names a method that does not exist on the service struct, is unexported, has a non-method receiver, or was renamed/removed in a newer version while the frontend bundle is stale.","commonSituations":"Version mismatch between frontend and backend after a refactor renaming a service method; typos in hand-written RPC call strings; calling an old generated TypeScript client against a newer backend; calling a method that exists but is not exported (lowercase first letter).","solutions":["Check the exact method name against the service struct in pkg/service/<service>/ and against the generated TypeScript client (tsgen output) — fix the caller's method name spelling/case","Rebuild/reload the frontend so the generated client matches the backend's current service methods","Confirm the method is exported (uppercase first letter) and defined on the service struct itself, not on a different type","Use CallService with a known-good method (e.g. from the _Meta tsgen annotations) to verify the service is registered under the expected name"],"exampleFix":"// before\nCallService(ctx, WebCallType{Service: \"workspace\", Method: \"createWorkspace\", ...})\n// after\nCallService(ctx, WebCallType{Service: \"workspace\", Method: \"CreateWorkspace\", ...})","handlingStrategy":"validation","validationCode":"const serviceMethods = { workspace: [\"CreateWorkspace\",\"UpdateWorkspace\",\"GetWorkspace\",\"DeleteWorkspace\"], window: [\"GetWindow\",\"CreateWindow\"] };\nfunction isValidCall(service, method) { return Array.isArray(serviceMethods[service]) && serviceMethods[service].includes(method); }\nif (!isValidCall(call.Service, call.Method)) throw new Error(`unknown method ${call.Service}.${call.Method}`);","typeGuard":"function isKnownMethod(service, method): method is keyof typeof serviceMethods[typeof service] {\n  return isValidCall(service, method);\n}","tryCatchPattern":null,"preventionTips":["Always call services through the tsgen-generated typed client, never hand-built method strings","Regenerate the client after any backend service signature change","Grep for method-name string literals in tests/scripts when renaming service methods"],"tags":["rpc","reflection","service"],"backgroundTag":"rpc-method-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}