wavetermdev/waveterm · error

failed to start durable shell: %w

Error message

failed to start durable shell: %w

What it means

This is the final wrapper around shellexec.StartRemoteShellJob, which actually spawns the durable remote shell job over the connection. Any failure launching that job (SSH exec failure, remote command error, job setup failure) is surfaced with this message. The durable shell was not created and no JobId is returned.

Source

Thrown at pkg/blockcontroller/durableshellcontroller.go:274

		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. Read the wrapped inner error for the precise remote-side failure.
  2. Test the same shell command over plain ssh (ssh host -t 'bash -l').
  3. Check the remote account's shell and authorized_keys for forced commands restricting exec.
  4. Verify the cmd/cmd-cwd meta values exist on the remote.
  5. Retry after fixing remote capacity issues (disk, sessions, permissions).

Example fix

// before
meta := waveobj.MetaMapType{"cmd": "/usr/local/bin/zsh", "conn": "server"} // zsh not installed remotely
// after
meta := waveobj.MetaMapType{"cmd": "/bin/bash", "conn": "server"} // shell that exists on the remote
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check meta before Start
if cmd := blockMeta.GetString(waveobj.MetaKey_Cmd, ""); cmd != "" {
    // ensure cmd exists remotely via a probe command if possible
}
if conn.DeriveConnStatus().Status != conncontroller.Status_Connected {
    return fmt.Errorf("remote not connected")
}

Try / catch

if err := controller.Start(ctx, meta, rtOpts, false); err != nil {
    var inner error
    errors.As(err, &inner) // unwrap 'failed to start durable shell' cause
    log.Printf("durable shell start failed: %v", inner)
    return err
}

Prevention

When it happens

Trigger: StartRemoteShellJob fails: the SSH channel cannot open, the remote shell command (cmdStr) fails, term/command options are invalid, or the remote refuses the interactive shell session.

Common situations: Remote user's default shell is invalid or restricted (rbash, nologin); server rejects interactive/login shells (MaxSessions, forced command in authorized_keys); disk-full or permission errors on the remote; cmd meta specifies a binary not present remotely.

Related errors


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