wavetermdev/waveterm · error
no context found in jwt token
Error message
no context found in jwt token
What it means
validateRpcContextFromAuth inspects the RpcContext decoded from a JWT auth token and rejects it when the token contains no context at all. The JWT must embed an RpcContext describing the peer's route/role.
Source
Thrown at pkg/wshutil/wshrouter_controlimpl.go:294
}
_, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateJobManagerVerify, data, &wshrpc.RpcOpts{Route: ControlRootRoute})
if err != nil {
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
- Regenerate the token so it includes the RpcContext claim
- Check the token-minting code path (e.g. MakeClientAuthToken) embeds RpcContext
- Upgrade mismatched client/server versions
Example fix
// before
token := jwt Sign({"sub": routeId})
// after
token := jwt Sign({"sub": routeId, "context": wshrpc.RpcContext{RouteId: routeId}}) Defensive patterns
Strategy: validation
Validate before calling
claims := decodeJwt(token)
if claims["context"] == nil {
return fmt.Errorf("token missing context claim")
} Type guard
func hasRpcContext(claims map[string]any) bool {
ctx, ok := claims["context"].(map[string]any)
return ok && ctx != nil
} Try / catch
routeId, err := validateRpcContextFromAuth(newCtx)
if err != nil {
// regenerate token with embedded RpcContext before retrying
} Prevention
- Always mint tokens via the shared helper that embeds RpcContext
- Add a decode-time assertion on the context claim
- Keep token schema versions aligned across client/server
When it happens
Trigger: Authenticating a connection with a JWT whose claims lack the RpcContext payload (nil after decoding).
Common situations: Token minted by an older/other client version that omitted the context claim; token manually crafted; claims dropped during token serialization.
Related errors
- error getting jwt public key: %v
- error extracting socket name from JWT: %v
- error authenticating with upstream: %v
- error making jwt token: %w
- failed to validate token: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/eb71287f107cfa94.
Report an issue: GitHub.