{"record":{"id":"27998c4c54e0fc08","repo":"wavetermdev/waveterm","slug":"no-token-entry-found","errorCode":null,"errorMessage":"no token entry found","messagePattern":"no token entry found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrouter_controlimpl.go","lineNumber":126,"sourceCode":"\t}\n\n\trtnData := wshrpc.CommandAuthenticateRtnData{RouteId: routeId}\n\tif newCtx.IsRouter {\n\t\tlog.Printf(\"wshrouter authenticate success linkid=%d (router)\", linkId)\n\t\timpl.Router.trustLink(linkId, LinkKind_Router)\n\t} else {\n\t\tlog.Printf(\"wshrouter authenticate success linkid=%d routeid=%q\", linkId, routeId)\n\t\timpl.Router.trustLink(linkId, LinkKind_Leaf)\n\t\timpl.Router.bindRoute(linkId, routeId, true)\n\t}\n\n\treturn rtnData, nil\n}\n\nfunc extractTokenData(token string) (wshrpc.CommandAuthenticateRtnData, error) {\n\tentry := shellutil.GetAndRemoveTokenSwapEntry(token)\n\tif entry == nil {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no token entry found\")\n\t}\n\t_, err := validateRpcContextFromAuth(entry.RpcContext)\n\tif err != nil {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, err\n\t}\n\tif entry.RpcContext.IsRouter {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"cannot auth router via token\")\n\t}\n\trouteId := entry.RpcContext.GenerateRouteId()\n\tif routeId == \"\" {\n\t\treturn wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf(\"no routeid\")\n\t}\n\treturn wshrpc.CommandAuthenticateRtnData{\n\t\tRouteId:        routeId,\n\t\tEnv:            entry.Env,\n\t\tInitScriptText: entry.ScriptText,\n\t\tRpcContext:     entry.RpcContext,\n\t}, nil","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrouter_controlimpl.go#L108-L144","documentation":"extractTokenData looks up the token string in the in-memory token-swap store via shellutil.GetAndRemoveTokenSwapEntry. Tokens issued for wsh connection are single-use: the entry is consumed (removed) on first successful verification. If the token string is not found in the store, this error is returned, meaning the token is unknown, already consumed, or was never issued by this process.","triggerScenarios":"Calling AuthenticateTokenCommand or AuthenticateTokenVerifyCommand with a token that (a) was never minted by shellutil token-swap, (b) was already redeemed once (single-use entries are removed on Get), or (c) was minted in a different server process/restart so the in-memory map no longer has it.","commonSituations":"Retrying a wsh connection after a first attempt already consumed the token; server restarted between token issuance and use; wsh connecting to the wrong server instance (token from another machine); copy of a token used by two clients.","solutions":["Generate a fresh token from the server and retry — token-swap entries are single-use and cannot be reused after the first verification.","Confirm wsh is connecting to the same server process that minted the token (a restart wipes the in-memory token map).","Ensure the token string is passed verbatim (no truncation or shell-mangled characters).","If automated retries are in place, re-mint a token per attempt rather than caching one."],"exampleFix":"// before\nerr := conn.AuthenticateToken(ctx, cachedToken) // second use -> gone\n// after\nfreshToken := server.MintConnectionToken() // mint a new single-use token each attempt\nerr := conn.AuthenticateToken(ctx, freshToken)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Go: on this error, re-mint the token and retry once\nrtn, err := conn.AuthenticateToken(ctx, token)\nif err != nil && strings.Contains(err.Error(), \"no token entry found\") {\n    token = mintFreshConnectionToken()\n    rtn, err = conn.AuthenticateToken(ctx, token)\n}","preventionTips":["Treat token-swap tokens as strictly single-use — never reuse after a successful auth","Re-mint a token for every connection attempt in automation","Avoid server restarts between minting and consuming a token"],"tags":["auth","token","single-use","rpc"],"backgroundTag":"single-use-token-already-consumed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}