{"record":{"id":"a423252797c4b347","repo":"wavetermdev/waveterm","slug":"error-getting-claims-from-token","errorCode":null,"errorMessage":"error getting claims from token","messagePattern":"error getting claims from token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshutil.go","lineNumber":367,"sourceCode":"\t\t\tif linkId != baseds.NoLinkId {\n\t\t\t\tDefaultRouter.UnregisterLink(baseds.LinkId(linkId))\n\t\t\t}\n\t\t}()\n\t\tAdaptStreamToMsgCh(conn, proxy.FromRemoteCh, readCallback)\n\t}()\n\tlinkId := DefaultRouter.RegisterUntrustedLink(proxy)\n\tlinkIdContainer.Store(int32(linkId))\n}\n\n// only for use on client\nfunc ExtractUnverifiedRpcContext(tokenStr string) (*wshrpc.RpcContext, error) {\n\ttoken, _, err := new(jwt.Parser).ParseUnverified(tokenStr, &wavejwt.WaveJwtClaims{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing token: %w\", err)\n\t}\n\tclaims, ok := token.Claims.(*wavejwt.WaveJwtClaims)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"error getting claims from token\")\n\t}\n\treturn claimsToRpcCtx(claims), nil\n}\n\n// only for use on client\nfunc ExtractUnverifiedSocketName(tokenStr string) (string, error) {\n\ttoken, _, err := new(jwt.Parser).ParseUnverified(tokenStr, &wavejwt.WaveJwtClaims{})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error parsing token: %w\", err)\n\t}\n\tclaims, ok := token.Claims.(*wavejwt.WaveJwtClaims)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"error getting claims from token\")\n\t}\n\tsockName := claims.Sock\n\tif sockName == \"\" {\n\t\treturn \"\", fmt.Errorf(\"sock claim is missing or invalid\")\n\t}","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshutil.go#L349-L385","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure the token was issued by the Wave server (wsh server) and is a Wave JWT, not a generic JWT","Check that client and server are the same Wave version so claim schemas match","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify the token decodes to a Wave-shaped claims object before calling\npayload, _ := base64.RawURLEncoding.DecodeString(strings.Split(tokenStr, \".\")[1])\nvar probe map[string]json.RawMessage\nif json.Unmarshal(payload, &probe) != nil || probe[\"aud\"] == nil {\n    return errors.New(\"not a Wave JWT\")\n}","typeGuard":null,"tryCatchPattern":"rpcCtx, err := wshutil.ExtractUnverifiedRpcContext(tokenStr)\nif err != nil {\n    return fmt.Errorf(\"token claims unusable; reissue token from Wave server: %w\", err)\n}","preventionTips":["Only pass tokens issued by the Wave server, never third-party JWTs","Pin matching client/server versions to avoid claim-schema drift","Treat this and the parse error together: regenerate the token on either"],"tags":["jwt","claims","type-assertion","wsh"],"backgroundTag":"jwt-invalid-claims","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}