wavetermdev/waveterm · error

no routeid

Error message

no routeid

What it means

After passing the IsRouter check, extractTokenData calls entry.RpcContext.GenerateRouteId() and requires a non-empty route id for leaf connections. An empty result means the stored RpcContext is a leaf that carries neither a RouteId nor a ProcRoute combination that produces a route id — the entry is effectively unusable for binding a route on the router.

Source

Thrown at pkg/wshutil/wshrouter_controlimpl.go:137

	return rtnData, nil
}

func extractTokenData(token string) (wshrpc.CommandAuthenticateRtnData, error) {
	entry := shellutil.GetAndRemoveTokenSwapEntry(token)
	if entry == nil {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no token entry found")
	}
	_, err := validateRpcContextFromAuth(entry.RpcContext)
	if err != nil {
		return wshrpc.CommandAuthenticateRtnData{}, err
	}
	if entry.RpcContext.IsRouter {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("cannot auth router via token")
	}
	routeId := entry.RpcContext.GenerateRouteId()
	if routeId == "" {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no routeid")
	}
	return wshrpc.CommandAuthenticateRtnData{
		RouteId:        routeId,
		Env:            entry.Env,
		InitScriptText: entry.ScriptText,
		RpcContext:     entry.RpcContext,
	}, nil
}

func (impl *WshRouterControlImpl) AuthenticateTokenVerifyCommand(ctx context.Context, data wshrpc.CommandAuthenticateTokenData) (wshrpc.CommandAuthenticateRtnData, error) {
	if !impl.Router.IsRootRouter() {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("authenticatetokenverify can only be called on root router")
	}
	if data.Token == "" {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no token in authenticatetoken message")
	}

	rtnData, err := extractTokenData(data.Token)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Re-mint the token ensuring RpcContext.RouteId is set (or ProcRoute is used appropriately) before swapping.
  2. Validate the RpcContext on the minting side with the same rules as validateRpcContextFromAuth (leaf must have a routeid).
  3. Check that token serialization/deserialization between processes preserves the RouteId field (no omitempty mismatches).

Example fix

// before
rpcCtx := &wshrpc.RpcContext{IsRouter: false} // no RouteId -> "no routeid"
// after
rpcCtx := &wshrpc.RpcContext{IsRouter: false, RouteId: "conn-abc123"}
Defensive patterns

Strategy: validation

Validate before calling

// validate before minting, mirroring validateRpcContextFromAuth
if !rpcCtx.IsRouter && rpcCtx.RouteId == "" && !rpcCtx.ProcRoute {
    return fmt.Errorf("leaf RpcContext requires a RouteId or ProcRoute")
}

Prevention

When it happens

Trigger: AuthenticateTokenCommand / AuthenticateTokenVerifyCommand with a token whose RpcContext has IsRouter=false but no RouteId (and no ProcRoute flag), so GenerateRouteId returns "".

Common situations: Hand-constructed RpcContext in custom token-minting scripts missing the RouteId field; a version mismatch where the minting side omits a field the verify side requires; JSON serialization dropping the field.

Related errors


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