wavetermdev/waveterm · error

invalid service: %q

Error message

invalid service: %q

What it means

CallService looks up the requested service name in the global ServiceMap; if webCall.Service is not registered, it returns this error quoting the unknown service name. It is the RPC layer's guard against dispatching to a nonexistent service object.

Source

Thrown at pkg/service/service.go:320

		}
		rtn.Data = val.Interface()
	}
	if rtn.Error == "" {
		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))

View on GitHub (pinned to a4447c1563)

Solutions

  1. Verify the exact registered service name (check RegisterService calls / ServiceMap keys) and fix the Service field spelling/case.
  2. Ensure the package registering the service is imported so its init() runs before the call.
  3. Update the client if the service was renamed or removed in a newer version.
  4. Add a startup assertion or list of known service names to catch drift early.

Example fix

// before
CallService(ctx, WebCallType{Service: "clientcontrol", ...})
// unknown name

// after
CallService(ctx, WebCallType{Service: "client", ...})
Defensive patterns

Strategy: validation

Validate before calling

const knownServices = ['client','fileshare','config', /* from ServiceMap registration */];
if (!knownServices.includes(webCall.Service)) throw new Error(`unknown service: ${webCall.Service}`);

Type guard

function isKnownService(name) { return typeof name === 'string' && knownServices.includes(name); }

Try / catch

try {
  const rtn = await callService(svc, method, args);
  if (rtn.error?.startsWith('invalid service')) {
    console.error('Service not registered or misnamed:', rtn.error);
  }
} catch (e) { /* log service name drift; check registration imports */ }

Prevention

When it happens

Trigger: Sending a WebCallType with a Service field that has no entry in ServiceMap — e.g. a typo ("Client" vs "client"), calling a service before its RegisterService init runs, or calling a service removed/renamed in a newer version.

Common situations: Frontend/backend version skew where the frontend calls a service the backend doesn't know; typos in service name strings; plugin code assuming a service exists without registering it; tests invoking CallService before test setup registers services.

Related errors


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