wavetermdev/waveterm · error

authentication returned empty routeid

Error message

authentication returned empty routeid

What it means

AuthenticateCommand succeeded at the transport level but returned an AuthRtnData with an empty RouteId. Wave assigns each authenticated client a route id used to address events and RPCs back to it; an empty RouteId means the server's response was incomplete or from an incompatible server version. Connect treats this as fatal because the client cannot register its route.

Source

Thrown at pkg/waveapp/waveapp.go:189

	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)},
	)
	if err != nil {
		return err
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Upgrade Wave Terminal and the waveapp to matching versions.
  2. Re-run Connect; if transient, a retry may return a populated RouteId.
  3. Log the full authRtnData response to confirm which fields came back.
  4. Check for a proxy or shim intercepting the control route.

Example fix

// before
if authRtnData.RouteId == "" { return fmt.Errorf("authentication returned empty routeid") }
// after: add diagnostics before failing
if authRtnData.RouteId == "" {
    log.Printf("auth response: %+v", authRtnData)
    return fmt.Errorf("authentication returned empty routeid (wave version mismatch?)")
}
Defensive patterns

Strategy: validation

Validate before calling

if authRtnData == nil || authRtnData.RouteId == "" {
    return fmt.Errorf("authentication returned no route id; check Wave/waveapp version match")
}

Type guard

func hasRouteId(d *wshrpc.AuthRtnData) bool {
    return d != nil && d.RouteId != ""
}

Try / catch

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 !hasRouteId(authRtnData) {
    return fmt.Errorf("authentication returned empty routeid")
}

Prevention

When it happens

Trigger: Calling Connect against a Wave Terminal version whose AuthenticateCommand response lacks RouteId, a server bug returning a zero-value response, or a decoding issue where the response fields were dropped.

Common situations: Mixing a new waveapp binary with an older Wave Terminal (or vice versa) so response schemas differ; custom/proxy RPC intermediaries stripping response fields.

Understand the failure class

Related errors


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