wavetermdev/waveterm · error

error making jwt token: %w

Error message

error making jwt token: %w

What it means

Wraps a failure from wshutil.MakeClientJWTToken while building the auth token injected into the environment for a WSL shell process. The JWT authenticates the wsh client back to Wave over the domain socket; without it the spawned shell cannot speak the wsh RPC protocol.

Source

Thrown at pkg/blockcontroller/shellcontroller.go:444

	blocklogger.Debugf(logCtx, "[conndebug] created swaptoken: %s\n", swapToken.Token)
	if connUnion.ConnType == ConnType_Wsl {
		wslConn := connUnion.WslConn
		if !connUnion.WshEnabled {
			shellProc, err = shellexec.StartWslShellProcNoWsh(ctx, rc.TermSize, cmdStr, cmdOpts, wslConn)
			if err != nil {
				return nil, err
			}
		} else {
			sockName := wslConn.GetDomainSocketName()
			rpcContext := wshrpc.RpcContext{
				ProcRoute: true,
				SockName:  sockName,
				BlockId:   bc.BlockId,
				Conn:      wslConn.GetName(),
			}
			jwtStr, err := wshutil.MakeClientJWTToken(rpcContext)
			if err != nil {
				return nil, fmt.Errorf("error making jwt token: %w", err)
			}
			swapToken.RpcContext = &rpcContext
			swapToken.Env[wshutil.WaveJwtTokenVarName] = jwtStr
			shellProc, err = shellexec.StartWslShellProc(ctx, rc.TermSize, cmdStr, cmdOpts, wslConn)
			if err != nil {
				wslConn.SetWshError(err)
				wslConn.WshEnabled.Store(false)
				blocklogger.Infof(logCtx, "[conndebug] error starting wsl shell proc with wsh: %v\n", err)
				blocklogger.Infof(logCtx, "[conndebug] attempting install without wsh\n")
				shellProc, err = shellexec.StartWslShellProcNoWsh(ctx, rc.TermSize, cmdStr, cmdOpts, wslConn)
				if err != nil {
					return nil, err
				}
			}
		}
	} else if connUnion.ConnType == ConnType_Ssh {
		conn := connUnion.SshConn
		if !connUnion.WshEnabled {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Verify Wave's key/secret files exist in the data directory with correct permissions and regenerate them if missing
  2. Ensure HOME/XDG paths point to the same data directory used when keys were created
  3. Restart Wave so key initialization runs again
  4. If migrating machines, copy the whole ~/.waveterm data dir (including key material), not just config

Example fix

// before: signing with whatever key is present
jwtStr, err := wshutil.MakeClientJWTToken(rpcContext)

// after: ensure key material is initialized first
if err := wshutil.EnsureKeyInitialized(); err != nil {
    return nil, fmt.Errorf("key material missing, reinit wave data dir: %w", err)
}
jwtStr, err := wshutil.MakeClientJWTToken(rpcContext)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure signing key exists before starting shells
if _, err := wshutil.GetWaveKey(); err != nil {
    return fmt.Errorf("wave key unavailable: %w", err)
}

Try / catch

proc, err := bc.setupAndStartShellProcess(logCtx, rc, blockMeta)
if err != nil && strings.Contains(err.Error(), "error making jwt token") {
    // reinit key material and retry once
}

Prevention

When it happens

Trigger: StartWslShellProc path: wshutil.MakeClientJWTToken(rpcContext) returns an error, typically because the Wave key/secret material needed to sign the token is missing or unreadable.

Common situations: ~/.waveterm secret/key files missing, zero-length, or with wrong permissions (e.g. app data copied between machines/users); running Wave with a different HOME so the key isn't found; first-run initialization interrupted so keys were never generated.

Related errors


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