wavetermdev/waveterm · error

invalid method: %s.%s

Error message

invalid method: %s.%s

What it means

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.

Source

Thrown at pkg/service/service.go:324

		rtn.Success = true
	}
	return rtn
}

func webErrorRtn(err error) *WebReturnType {
	return &WebReturnType{
		Error: err.Error(),
	}
}

func CallService(ctx context.Context, webCall WebCallType) *WebReturnType {
	svcObj := ServiceMap[webCall.Service]
	if svcObj == nil {
		return webErrorRtn(fmt.Errorf("invalid service: %q", webCall.Service))
	}
	method := reflect.ValueOf(svcObj).MethodByName(webCall.Method)
	if !method.IsValid() {
		return webErrorRtn(fmt.Errorf("invalid method: %s.%s", webCall.Service, webCall.Method))
	}
	var valueArgs []reflect.Value
	argIdx := 0
	for idx := 0; idx < method.Type().NumIn(); idx++ {
		argType := method.Type().In(idx)
		if idx == 0 && argType == contextRType {
			valueArgs = append(valueArgs, reflect.ValueOf(ctx))
			continue
		}
		if argType == uiContextRType {
			if webCall.UIContext == nil {
				return webErrorRtn(fmt.Errorf("missing UIContext for %s.%s", webCall.Service, webCall.Method))
			}
			valueArgs = append(valueArgs, reflect.ValueOf(*webCall.UIContext))
			continue
		}
		if argIdx >= len(webCall.Args) {
			return webErrorRtn(fmt.Errorf("not enough arguments passed %s.%s idx:%d (type %T)", webCall.Service, webCall.Method, idx, argType))

View on GitHub (pinned to a4447c1563)

Solutions

  1. 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
  2. Rebuild/reload the frontend so the generated client matches the backend's current service methods
  3. Confirm the method is exported (uppercase first letter) and defined on the service struct itself, not on a different type
  4. Use CallService with a known-good method (e.g. from the _Meta tsgen annotations) to verify the service is registered under the expected name

Example fix

// before
CallService(ctx, WebCallType{Service: "workspace", Method: "createWorkspace", ...})
// after
CallService(ctx, WebCallType{Service: "workspace", Method: "CreateWorkspace", ...})
Defensive patterns

Strategy: validation

Validate before calling

const serviceMethods = { workspace: ["CreateWorkspace","UpdateWorkspace","GetWorkspace","DeleteWorkspace"], window: ["GetWindow","CreateWindow"] };
function isValidCall(service, method) { return Array.isArray(serviceMethods[service]) && serviceMethods[service].includes(method); }
if (!isValidCall(call.Service, call.Method)) throw new Error(`unknown method ${call.Service}.${call.Method}`);

Type guard

function isKnownMethod(service, method): method is keyof typeof serviceMethods[typeof service] {
  return isValidCall(service, method);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


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