{"record":{"id":"f1114ee009af2b8e","repo":"wavetermdev/waveterm","slug":"failed-to-verify-token-w","errorCode":null,"errorMessage":"failed to verify token: %w","messagePattern":"failed to verify token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":196,"sourceCode":"\n\tvar rtnData wshrpc.CommandAuthenticateRtnData\n\tvar err error\n\n\tif impl.Router.IsRootRouter() {\n\t\trtnData, err = extractTokenData(data.Token)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"wshrouter authenticate-token error linkid=%d: %v\", linkId, err)\n\t\t\treturn wshrpc.CommandAuthenticateRtnData{}, err\n\t\t}\n\t} else {\n\t\twshRpc := GetWshRpcFromContext(ctx)\n\t\tif wshRpc == nil {\n\t\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no wshrpc in context\")\n\t\t}\n\t\trespData, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateTokenVerify, data, &wshrpc.RpcOpts{Route: ControlRootRoute})\n\t\tif err != nil {\n\t\t\tlog.Printf(\"wshrouter authenticate-token error linkid=%d: failed to verify token: %v\", linkId, err)\n\t\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"failed to verify token: %w\", err)\n\t\t}\n\t\terr = utilfn.ReUnmarshal(&rtnData, respData)\n\t\tif err != nil {\n\t\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"failed to unmarshal response: %w\", err)\n\t\t}\n\t}\n\n\tif rtnData.RpcContext == nil {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no rpccontext in token response\")\n\t}\n\tif rtnData.RouteId == \"\" {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no routeid in token response\")\n\t}\n\tlog.Printf(\"wshrouter authenticate-token success linkid=%d routeid=%q\", linkId, rtnData.RouteId)\n\timpl.Router.trustLink(linkId, LinkKind_Leaf)\n\timpl.Router.bindRoute(linkId, rtnData.RouteId, true)\n\n\treturn rtnData, nil","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L178-L214","documentation":"This error is returned by AuthenticateTokenCommand when the router is NOT the root router and the forwarded AuthenticateTokenVerify RPC to the root router (via ControlRootRoute) fails. It wraps the underlying transport/RPC error, so the root cause is chained via %w. It indicates the token could not be verified upstream, not that the token itself is necessarily bad.","triggerScenarios":"Calling authenticate-token on a non-root router whose SendRpcRequest(Command_AuthenticateTokenVerify) to the control root route fails — e.g. no route to root, root not connected, RPC timeout, or the remote AuthenticateTokenVerifyCommand returning an error (invalid/expired token).","commonSituations":"Relay/middle-layer router forwarding a leaf's connection handshake while the upstream link to the root is down; token expired or revoked on the root; typo in route to ControlRootRoute; network drop mid-handshake.","solutions":["Inspect the wrapped error (%w chain / errors.Unwrap) to find the root cause (timeout vs route-not-found vs invalid token).","Verify the router has an active connection to the root router and that ControlRootRoute is registered.","Regenerate the auth token on the root and retry the authenticate-token handshake.","Check wshrouter logs for the matching 'authenticate-token error linkid=...' line to see the raw underlying error."],"exampleFix":"// before\nrespData, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateTokenVerify, data, &wshrpc.RpcOpts{Route: ControlRootRoute})\nif err != nil {\n    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"failed to verify token: %w\", err)\n}\n// after\nrespData, err := wshRpc.SendRpcRequest(wshrpc.Command_AuthenticateTokenVerify, data, &wshrpc.RpcOpts{Route: ControlRootRoute, Timeout: 10 * time.Second})\nif err != nil {\n    if errors.Is(err, wshutil.ErrRouteNotFound) {\n        return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"root router unreachable: %w\", err)\n    }\n    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"failed to verify token: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// caller-side: only attempt when a route to the root is likely registered\nif !router.HasRoute(wshutil.ControlRootRoute) {\n    return fmt.Errorf(\"root router not connected; cannot verify token yet\")\n}","typeGuard":"func errIsTransport(err error) bool {\n    var netErr net.Error\n    return errors.As(err, &netErr)\n}","tryCatchPattern":"rtn, err := router.AuthenticateTokenCommand(ctx, data)\nif err != nil {\n    var wrapped *wshutil.RpcErr\n    if errors.As(err, &wrapped) || errors.Is(err, context.DeadlineExceeded) {\n        // transient: retry with backoff\n        return retryWithBackoff(func() error { _, err := router.AuthenticateTokenCommand(ctx, data); return err })\n    }\n    return fmt.Errorf(\"token verify failed permanently: %w\", err)\n}","preventionTips":["Always keep an active root-router connection before starting the token handshake.","Set explicit RPC timeouts so verification failures surface quickly and can be retried.","Regenerate tokens regularly and match client/server wshutil versions.","Read the wrapped cause with errors.Unwrap before deciding on retry vs abort."],"tags":["rpc","authentication","network"],"backgroundTag":"rpc-token-verification-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}