wavetermdev/waveterm · error

invalid context, router cannot have a routeid

Error message

invalid context, router cannot have a routeid

What it means

Sentinel/creation-time validation: a router (as opposed to an RPC endpoint) context must not carry a route ID. This error is returned when building or validating a router context that unexpectedly has a route ID set, which would corrupt routing semantics.

Source

Thrown at pkg/wshutil/wshrouter_controlimpl.go:297

			log.Printf("wshrouter authenticate-jobmanager error linkid=%d jobid=%q: failed to verify job auth token: %v", linkId, data.JobId, err)
			return fmt.Errorf("failed to verify job auth token: %w", err)
		}
	}

	routeId := MakeJobRouteId(data.JobId)
	log.Printf("wshrouter authenticate-jobmanager success linkid=%d jobid=%q routeid=%q", linkId, data.JobId, routeId)
	impl.Router.trustLink(linkId, LinkKind_Leaf)
	impl.Router.bindRoute(linkId, routeId, true)

	return nil
}

func validateRpcContextFromAuth(newCtx *wshrpc.RpcContext) (string, error) {
	if newCtx == nil {
		return "", fmt.Errorf("no context found in jwt token")
	}
	if newCtx.IsRouter && newCtx.RouteId != "" {
		return "", fmt.Errorf("invalid context, router cannot have a routeid")
	}
	if newCtx.IsRouter && newCtx.ProcRoute {
		return "", fmt.Errorf("invalid context, router cannot have a proc-route")
	}
	if !newCtx.IsRouter && newCtx.RouteId == "" && !newCtx.ProcRoute {
		return "", fmt.Errorf("invalid context, must have a routeid")
	}
	if newCtx.IsRouter {
		return "", nil
	}
	return newCtx.GenerateRouteId(), nil
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set RouteId to "" when IsRouter is true in the token's RpcContext
  2. Fix token-minting code to build the router context without a route id
  3. Use the correct context constructor for router vs leaf connections

Example fix

// before
ctx := wshrpc.RpcContext{IsRouter: true, RouteId: myRouteId}
// after
ctx := wshrpc.RpcContext{IsRouter: true, RouteId: ""}
Defensive patterns

Strategy: validation

Validate before calling

if newCtx.IsRouter && newCtx.RouteId != "" {
    return fmt.Errorf("router token context must not set RouteId")
}

Type guard

func validRouterContext(c *wshrpc.RpcContext) bool {
    return c.IsRouter && c.RouteId == "" && !c.ProcRoute
}

Try / catch

if _, err := validateRpcContextFromAuth(newCtx); err != nil {
    // rebuild and re-mint the token with a router context (RouteId empty)
}

Prevention

When it happens

Trigger: Authenticating with a token whose RpcContext has IsRouter:true and RouteId != "".

Common situations: Client code confusing its own route id with router identity when building the token; copy-pasted context structs between leaf and router clients.

Related errors


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