{"record":{"id":"b3dc475eb0174563","repo":"wavetermdev/waveterm","slug":"no-routeid-in-token-response","errorCode":null,"errorMessage":"no routeid in token response","messagePattern":"no routeid in token response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":208,"sourceCode":"\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\n}\n\nfunc (impl *WshRouterControlImpl) AuthenticateJobManagerVerifyCommand(ctx context.Context, data wshrpc.CommandAuthenticateJobManagerData) error {\n\tif !impl.Router.IsRootRouter() {\n\t\treturn fmt.Errorf(\"authenticatejobmanagerverify can only be called on root router\")\n\t}\n\n\tif data.JobId == \"\" {\n\t\treturn fmt.Errorf(\"no jobid in authenticatejobmanager message\")\n\t}\n\tif data.JobAuthToken == \"\" {\n\t\treturn fmt.Errorf(\"no jobauthtoken in authenticatejobmanager message\")","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L190-L226","documentation":"Token verification returned data but RouteId is empty, so the router cannot bind the authenticated link to a route. RouteId is what ties the trusted link to the peer's route in the routing table; without it the handshake cannot complete.","triggerScenarios":"The root's token-verify response contains a CommandAuthenticateRtnData whose RouteId field is \"\" — e.g. token generated without a route id, or the root failed to fill RouteId before responding.","commonSituations":"Stale or hand-edited connection tokens; tokens created by older versions that did not embed the route id; root router returning a zero-value response after a partial failure.","solutions":["Regenerate the connection token on the root and re-authenticate.","Check the root code that sets rtnData.RouteId (from the token payload) and confirm it is populated.","Verify no version skew drops the route id field during serialization.","Inspect the token contents to confirm it embeds the intended route id."],"exampleFix":"// before\nif rtnData.RouteId == \"\" {\n    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no routeid in token response\")\n}\n// after\nif rtnData.RouteId == \"\" {\n    return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no routeid in token response (token may be stale; regenerate it)\")\n}","handlingStrategy":"validation","validationCode":"// ensure token carries a route id before handshake\nparsed, err := extractTokenData(token)\nif err == nil && parsed.RouteId == \"\" {\n    return fmt.Errorf(\"token has empty route id; regenerate connection token\")\n}","typeGuard":"func hasRouteId(d wshrpc.CommandAuthenticateRtnData) bool {\n    return d.RouteId != \"\"\n}","tryCatchPattern":"rtn, err := router.AuthenticateTokenCommand(ctx, data)\nif err != nil && strings.Contains(err.Error(), \"no routeid in token response\") {\n    return fmt.Errorf(\"stale token; regenerate and retry once: %w\", err)\n}","preventionTips":["Never hand-edit or reuse old connection tokens.","Regenerate the token whenever the route is recreated.","Test that token generation embeds a non-empty route id."],"tags":["authentication","routing","rpc"],"backgroundTag":"missing-route-id-in-token-response","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}