wavetermdev/waveterm · error

error authenticating rpc connection: %v

Error message

error authenticating rpc connection: %v

What it means

The RPC transport is up, but the AuthenticateCommand RPC sent over the ControlRoute failed. Wave requires the client to prove its identity by presenting the JWT before any further RPCs are honored. Failures here indicate the server rejected the call (invalid/expired token), the response never arrived (timeout), or routing to the control endpoint failed.

Source

Thrown at pkg/waveapp/waveapp.go:186

		return fmt.Errorf("error extracting rpc context from %s: %v", wshutil.WaveJwtTokenVarName, err)
	}
	client.RpcContext = rpcCtx
	if client.RpcContext == nil || client.RpcContext.BlockId == "" {
		return fmt.Errorf("no block id in rpc context")
	}
	client.ServerImpl = &WaveAppServerImpl{BlockId: client.RpcContext.BlockId, Client: client}
	sockName, err := wshutil.ExtractUnverifiedSocketName(jwtToken)
	if err != nil {
		return fmt.Errorf("error extracting socket name from %s: %v", wshutil.WaveJwtTokenVarName, err)
	}
	rpcClient, err := wshutil.SetupDomainSocketRpcClient(sockName, client.ServerImpl, "vdomclient")
	if err != nil {
		return fmt.Errorf("error setting up domain socket rpc client: %v", err)
	}
	client.RpcClient = rpcClient
	authRtnData, err := wshclient.AuthenticateCommand(client.RpcClient, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRoute})
	if err != nil {
		return fmt.Errorf("error authenticating rpc connection: %v", err)
	}
	if authRtnData.RouteId == "" {
		return fmt.Errorf("authentication returned empty routeid")
	}
	client.RouteId = authRtnData.RouteId
	return nil
}

func (c *Client) SetRootElem(elem *vdom.VDomElem) {
	c.RootElem = elem
}

func (c *Client) CreateVDomContext(target *vdom.VDomTarget) error {
	blockORef, err := wshclient.VDomCreateContextCommand(
		c.RpcClient,
		vdom.VDomCreateContext{Target: target},
		&wshrpc.RpcOpts{Route: wshutil.MakeFeBlockRouteId(c.RpcContext.BlockId)},
	)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Relaunch the app from a fresh Wave block to obtain a new JWT token and retry.
  2. Check clock synchronization on the host (token expiry is time-based).
  3. Confirm the Wave Terminal version matches the waveapp/wsh client libraries.
  4. Retry after verifying Wave is responsive (other wsh commands work in the block).
  5. Inspect the wrapped %v error for 'timeout' vs explicit rejection to pick between retry and re-auth.

Example fix

// before: single auth attempt with stale token
authRtnData, err := wshclient.AuthenticateCommand(client.RpcClient, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRoute})
// after: retry transient failures
var authRtnData *wshrpc.AuthRtnData
for i := 0; i < 3; i++ {
    authRtnData, err = wshclient.AuthenticateCommand(client.RpcClient, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRoute})
    if err == nil { break }
    time.Sleep(time.Second)
}
Defensive patterns

Strategy: retry

Validate before calling

if jwtToken == "" {
    return fmt.Errorf("cannot authenticate: empty JWT token")
}
// ensure host clock is sane if tokens carry expiry claims

Try / catch

authRtnData, err := wshclient.AuthenticateCommand(client.RpcClient, jwtToken, &wshrpc.RpcOpts{Route: wshutil.ControlRoute})
if err != nil {
    if strings.Contains(err.Error(), "timeout") {
        // transient: retry once with fresh client
    }
    return fmt.Errorf("error authenticating rpc connection: %v", err)
}

Prevention

When it happens

Trigger: Calling Connect when the JWT token has expired or was revoked, the control route is unreachable, the Wave host rejects the handshake, or the RPC times out because the Wave process is unresponsive.

Common situations: Long-running environments where the token TTL expired; system clock skew invalidating token timestamps; Wave busy/hung so the authentication response never returns; version mismatch where the server no longer accepts the client's auth payload shape.

Understand the failure class

Related errors


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