wavetermdev/waveterm · error
no wshrpc in context
Error message
no wshrpc in context
What it means
When AuthenticateTokenCommand runs on a non-root router, it forwards the token to the root via SendRpcRequest using the WshRpc instance taken from the context (GetWshRpcFromContext). This error means the context did not carry a WshRpc, so the router cannot proxy the verification request to the root router.
Source
Thrown at pkg/wshutil/wshrouter_controlimpl.go:191
}
if data.Token == "" {
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no token in authenticatetoken message")
}
var rtnData wshrpc.CommandAuthenticateRtnData
var err error
if impl.Router.IsRootRouter() {
rtnData, err = extractTokenData(data.Token)
if err != nil {
log.Printf("wshrouter authenticate-token error linkid=%d: %v", linkId, err)
return wshrpc.CommandAuthenticateRtnData{}, err
}
} else {
wshRpc := GetWshRpcFromContext(ctx)
if wshRpc == nil {
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no wshrpc in context")
}
respData, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateTokenVerify, data, &wshrpc.RpcOpts{Route: ControlRootRoute})
if err != nil {
log.Printf("wshrouter authenticate-token error linkid=%d: failed to verify token: %v", linkId, err)
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("failed to verify token: %w", err)
}
err = utilfn.ReUnmarshal(&rtnData, respData)
if err != nil {
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("failed to unmarshal response: %w", err)
}
}
if rtnData.RpcContext == nil {
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no rpccontext in token response")
}
if rtnData.RouteId == "" {
return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no routeid in token response")
}View on GitHub (pinned to a4447c1563)
Solutions
- Invoke the command through the normal wshrpc dispatch so GetWshRpcFromContext finds the router's WshRpc instance.
- In tests/tools, inject the WshRpc into the context using the wshutil context helper before calling the command.
- Ensure router/proxy initialization completes (WshRpc registered) before any token authentication is attempted.
Example fix
// before impl.AuthenticateTokenCommand(context.Background(), data) // no WshRpc -> error // after ctx := wshutil.CtxWithWshRpc(context.Background(), router.GetWshRpc()) impl.AuthenticateTokenCommand(ctx, data)
Defensive patterns
Strategy: try-catch
Validate before calling
// before calling on a non-root router
if !router.IsRootRouter() && wshutil.GetWshRpcFromContext(ctx) == nil {
return fmt.Errorf("context lacks WshRpc; initialize router plumbing before token auth")
} Type guard
// Go: nil-check narrowing on the rpc
wshRpc := wshutil.GetWshRpcFromContext(ctx)
if wshRpc == nil {
return fmt.Errorf("no wshrpc in context")
} Try / catch
// Go
rtn, err := impl.AuthenticateTokenCommand(ctx, data)
if err != nil && strings.Contains(err.Error(), "no wshrpc in context") {
return fmt.Errorf("router forwarding unavailable; ensure dispatch injected WshRpc: %w", err)
} Prevention
- Invoke control commands via the standard wshrpc dispatch path
- Complete router/proxy initialization before attempting authentication
- In tests, inject the WshRpc into the context with wshutil helpers
When it happens
Trigger: AuthenticateTokenCommand executing on a non-root router with a context lacking the WshRpc context value — typically a manually constructed context or a dispatch path that did not inject the local WshRpc.
Common situations: Custom or test harnesses calling control commands with context.Background(); intermediate router setups where the wshrpc plumbing was not initialized before authentication was attempted; goroutines that detached the original dispatch context.
Related errors
- error setting up rpc client: %w
- error getting connection name from context: %v
- error getting rpc response handler from context
- error validating token: %w
- no token entry found
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/3c7d9ad01e5a4ad8.
Report an issue: GitHub.