wavetermdev/waveterm · error

no routeid in token response

Error message

no routeid in token response

What it means

Token verification returned data but RouteId is empty, so the router cannot bind the authenticated link to a route. RouteId is what ties the trusted link to the peer's route in the routing table; without it the handshake cannot complete.

Source

Thrown at pkg/wshutil/wshrouter_controlimpl.go:208

		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")
	}
	log.Printf("wshrouter authenticate-token success linkid=%d routeid=%q", linkId, rtnData.RouteId)
	impl.Router.trustLink(linkId, LinkKind_Leaf)
	impl.Router.bindRoute(linkId, rtnData.RouteId, true)

	return rtnData, nil
}

func (impl *WshRouterControlImpl) AuthenticateJobManagerVerifyCommand(ctx context.Context, data wshrpc.CommandAuthenticateJobManagerData) error {
	if !impl.Router.IsRootRouter() {
		return fmt.Errorf("authenticatejobmanagerverify can only be called on root router")
	}

	if data.JobId == "" {
		return fmt.Errorf("no jobid in authenticatejobmanager message")
	}
	if data.JobAuthToken == "" {
		return fmt.Errorf("no jobauthtoken in authenticatejobmanager message")

View on GitHub (pinned to a4447c1563)

Solutions

  1. Regenerate the connection token on the root and re-authenticate.
  2. Check the root code that sets rtnData.RouteId (from the token payload) and confirm it is populated.
  3. Verify no version skew drops the route id field during serialization.
  4. Inspect the token contents to confirm it embeds the intended route id.

Example fix

// before
if rtnData.RouteId == "" {
    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no routeid in token response")
}
// after
if rtnData.RouteId == "" {
    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no routeid in token response (token may be stale; regenerate it)")
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure token carries a route id before handshake
parsed, err := extractTokenData(token)
if err == nil && parsed.RouteId == "" {
    return fmt.Errorf("token has empty route id; regenerate connection token")
}

Type guard

func hasRouteId(d wshrpc.CommandAuthenticateRtnData) bool {
    return d.RouteId != ""
}

Try / catch

rtn, err := router.AuthenticateTokenCommand(ctx, data)
if err != nil && strings.Contains(err.Error(), "no routeid in token response") {
    return fmt.Errorf("stale token; regenerate and retry once: %w", err)
}

Prevention

When it happens

Trigger: The root's token-verify response contains a CommandAuthenticateRtnData whose RouteId field is "" — e.g. token generated without a route id, or the root failed to fill RouteId before responding.

Common situations: Stale or hand-edited connection tokens; tokens created by older versions that did not embed the route id; root router returning a zero-value response after a partial failure.

Related errors


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