wavetermdev/waveterm · error

error making jwt token: %w

Error message

error making jwt token: %w

What it means

Before launching the remote shell, the controller mints a JWT token (wshutil.MakeClientJWTToken) that authenticates the spawned shell's wsh RPC back to the app, injected via the swap token environment. This error means local token generation failed — typically missing signing key material or malformed RpcContext.

Source

Thrown at pkg/blockcontroller/durableshellcontroller.go:261

		return "", fmt.Errorf("connection %q not found", connName)
	}
	connRoute := wshutil.MakeConnectionRouteId(connName)
	remoteInfo, err := wshclient.RemoteGetInfoCommand(wshclient.GetBareRpcClient(), &wshrpc.RpcOpts{Route: connRoute, Timeout: 2000})
	if err != nil {
		return "", fmt.Errorf("unable to obtain remote info from connserver: %w", err)
	}
	shellType := shellutil.GetShellTypeFromShellPath(remoteInfo.Shell)
	swapToken := makeSwapToken(ctx, ctx, dsc.BlockId, blockMeta, connName, shellType)
	sockName := wavebase.GetPersistentRemoteSockName(wstore.GetClientId())
	rpcContext := wshrpc.RpcContext{
		ProcRoute: true,
		SockName:  sockName,
		BlockId:   dsc.BlockId,
		Conn:      connName,
	}
	jwtStr, err := wshutil.MakeClientJWTToken(rpcContext)
	if err != nil {
		return "", fmt.Errorf("error making jwt token: %w", err)
	}
	swapToken.RpcContext = &rpcContext
	swapToken.Env[wshutil.WaveJwtTokenVarName] = jwtStr
	cmdOpts := shellexec.CommandOptsType{
		Interactive: true,
		Login:       true,
		Cwd:         cwd,
		SwapToken:   swapToken,
		ForceJwt:    blockMeta.GetBool(waveobj.MetaKey_CmdJwt, false),
	}
	jobId, err := shellexec.StartRemoteShellJob(ctx, ctx, termSize, cmdStr, cmdOpts, conn, dsc.BlockId)
	if err != nil {
		return "", fmt.Errorf("failed to start durable shell: %w", err)
	}
	return jobId, nil
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check that the local wave config directory and its key material exist and are readable.
  2. Reset the app's key/config state (re-initialize config) if keys are corrupt.
  3. Verify RpcContext fields (SockName, BlockId, Conn) are non-empty and correct.
  4. Inspect the wrapped inner error for the exact crypto/token failure.

Example fix

// before
rpcContext := wshrpc.RpcContext{ProcRoute: true} // missing Route/fields, token gen fails
// after
rpcContext := wshrpc.RpcContext{ProcRoute: true, Route: connRoute, BlockId: dsc.BlockId, SockName: sockName, Conn: connName}
jwtStr, err := wshutil.MakeClientJWTToken(rpcContext)
Defensive patterns

Strategy: try-catch

Try / catch

if _, err := controller.Start(ctx, meta, rtOpts, false); err != nil {
    if strings.Contains(err.Error(), "jwt token") {
        // regenerate/repair local key material, then retry
    }
    return err
}

Prevention

When it happens

Trigger: MakeClientJWTToken returns an error: the client's signing key/secret is missing or unreadable, or the constructed RpcContext (ProcRoute, SockName, BlockId, Conn) is invalid for token claims.

Common situations: Corrupted or missing local key/config files after a bad install or profile copy; running in a sandbox/home-dir without the expected wave config; clock/claims issues in extreme cases.

Related errors


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