wavetermdev/waveterm · error

no token entry found

Error message

no token entry found

What it means

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.

Source

Thrown at pkg/wshutil/wshrouter_controlimpl.go:126

	}

	rtnData := wshrpc.CommandAuthenticateRtnData{RouteId: routeId}
	if newCtx.IsRouter {
		log.Printf("wshrouter authenticate success linkid=%d (router)", linkId)
		impl.Router.trustLink(linkId, LinkKind_Router)
	} else {
		log.Printf("wshrouter authenticate success linkid=%d routeid=%q", linkId, routeId)
		impl.Router.trustLink(linkId, LinkKind_Leaf)
		impl.Router.bindRoute(linkId, routeId, true)
	}

	return rtnData, nil
}

func extractTokenData(token string) (wshrpc.CommandAuthenticateRtnData, error) {
	entry := shellutil.GetAndRemoveTokenSwapEntry(token)
	if entry == nil {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no token entry found")
	}
	_, err := validateRpcContextFromAuth(entry.RpcContext)
	if err != nil {
		return wshrpc.CommandAuthenticateRtnData{}, err
	}
	if entry.RpcContext.IsRouter {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("cannot auth router via token")
	}
	routeId := entry.RpcContext.GenerateRouteId()
	if routeId == "" {
		return wshrpc.CommandAuthenticateRtnData{}, fmt.Errorf("no routeid")
	}
	return wshrpc.CommandAuthenticateRtnData{
		RouteId:        routeId,
		Env:            entry.Env,
		InitScriptText: entry.ScriptText,
		RpcContext:     entry.RpcContext,
	}, nil

View on GitHub (pinned to a4447c1563)

Solutions

  1. Generate a fresh token from the server and retry — token-swap entries are single-use and cannot be reused after the first verification.
  2. Confirm wsh is connecting to the same server process that minted the token (a restart wipes the in-memory token map).
  3. Ensure the token string is passed verbatim (no truncation or shell-mangled characters).
  4. If automated retries are in place, re-mint a token per attempt rather than caching one.

Example fix

// before
err := conn.AuthenticateToken(ctx, cachedToken) // second use -> gone
// after
freshToken := server.MintConnectionToken() // mint a new single-use token each attempt
err := conn.AuthenticateToken(ctx, freshToken)
Defensive patterns

Strategy: retry

Try / catch

// Go: on this error, re-mint the token and retry once
rtn, err := conn.AuthenticateToken(ctx, token)
if err != nil && strings.Contains(err.Error(), "no token entry found") {
    token = mintFreshConnectionToken()
    rtn, err = conn.AuthenticateToken(ctx, token)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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