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
- Verify the exact registered service name (check RegisterService calls / ServiceMap keys) and fix the Service field spelling/case.
- Ensure the package registering the service is imported so its init() runs before the call.
- Update the client if the service was renamed or removed in a newer version.
- 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
- Keep service name constants shared between client and server instead of raw strings.
- Verify the package calling RegisterService is imported (init side effects).
- Check for version skew when frontend and backend deploy independently.
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
- unsupported command type %q
- call ${methodName} error: ${respData.error}
- rpc command "${msg.command}" not supported by [${this.routeI
- msg.error
- source cannot be blank
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/14fe01dfc47b6efd.
Report an issue: GitHub.