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

  1. Regenerate the token so it includes the RpcContext claim
  2. Check the token-minting code path (e.g. MakeClientAuthToken) embeds RpcContext
  3. 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

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


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