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

  1. Invoke the command through the normal wshrpc dispatch so GetWshRpcFromContext finds the router's WshRpc instance.
  2. In tests/tools, inject the WshRpc into the context using the wshutil context helper before calling the command.
  3. 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

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


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