wavetermdev/waveterm · error

error getting claims from token

Error message

error getting claims from token

What it means

After ParseUnverified succeeds, the code asserts token.Claims to *wavejwt.WaveJwtClaims. This error means the assertion failed, i.e. the parser produced a different claims type, which occurs when the token's claims payload is not valid JSON matching the WaveJwtClaims structure.

Solutions

  1. Ensure the token was issued by the Wave server (wsh server) and is a Wave JWT, not a generic JWT
  2. Check that client and server are the same Wave version so claim schemas match
  3. Note that ParseUnverified with a typed claims pointer rarely fails this way — prefer checking error 1570 (parse failure) first; if it persists, re-generate the token
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the token decodes to a Wave-shaped claims object before calling
payload, _ := base64.RawURLEncoding.DecodeString(strings.Split(tokenStr, ".")[1])
var probe map[string]json.RawMessage
if json.Unmarshal(payload, &probe) != nil || probe["aud"] == nil {
    return errors.New("not a Wave JWT")
}

Try / catch

rpcCtx, err := wshutil.ExtractUnverifiedRpcContext(tokenStr)
if err != nil {
    return fmt.Errorf("token claims unusable; reissue token from Wave server: %w", err)
}

Prevention

When it happens

Trigger: Calling ExtractUnverifiedRpcContext on a JWT whose payload decodes to a non-object or claims JSON that does not unmarshal into WaveJwtClaims (unexpected claim shape produced by a non-Wave JWT issuer).

Common situations: Passing a third-party JWT (e.g. from another service) to a Wave API; server and client built from incompatible versions with different claim schemas; manually constructed test tokens.

Related errors


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

Appendix: source

Thrown at pkg/wshutil/wshutil.go:367

			if linkId != baseds.NoLinkId {
				DefaultRouter.UnregisterLink(baseds.LinkId(linkId))
			}
		}()
		AdaptStreamToMsgCh(conn, proxy.FromRemoteCh, readCallback)
	}()
	linkId := DefaultRouter.RegisterUntrustedLink(proxy)
	linkIdContainer.Store(int32(linkId))
}

// only for use on client
func ExtractUnverifiedRpcContext(tokenStr string) (*wshrpc.RpcContext, error) {
	token, _, err := new(jwt.Parser).ParseUnverified(tokenStr, &wavejwt.WaveJwtClaims{})
	if err != nil {
		return nil, fmt.Errorf("error parsing token: %w", err)
	}
	claims, ok := token.Claims.(*wavejwt.WaveJwtClaims)
	if !ok {
		return nil, fmt.Errorf("error getting claims from token")
	}
	return claimsToRpcCtx(claims), nil
}

// only for use on client
func ExtractUnverifiedSocketName(tokenStr string) (string, error) {
	token, _, err := new(jwt.Parser).ParseUnverified(tokenStr, &wavejwt.WaveJwtClaims{})
	if err != nil {
		return "", fmt.Errorf("error parsing token: %w", err)
	}
	claims, ok := token.Claims.(*wavejwt.WaveJwtClaims)
	if !ok {
		return "", fmt.Errorf("error getting claims from token")
	}
	sockName := claims.Sock
	if sockName == "" {
		return "", fmt.Errorf("sock claim is missing or invalid")
	}

View on GitHub (pinned to a4447c1563)