Troubleshooting

Troubleshooting

Diagnose common CLI and tunnel issues.


This page collects common failure modes for CLI setup, tunnel runtime, signaling, and WebTTY. It focuses on checks that are safe to run without printing secrets.

Start with doctor

rstream doctor is the first command to run after setup changes or when the CLI cannot reach the expected project. The JSON output is designed for agents and CI because it reports structured checks without printing token values.

rstream doctor -o json

The report includes local configuration loading, selected context, token presence and decoded claims, Control plane API authentication, project endpoint resolution, engine address parsing, DNS, TLS or QUIC transport checks, and engine inventory. Each check has a status of pass, warn, fail, or skip.

fail means the next action usually starts with that check. A missing token is fixed before investigating engine inventory. A project resolution failure is fixed before testing DNS or TLS. skip usually means a prerequisite was unavailable, such as no configured engine or no token.

For engine-only contexts created with --no-api-url, Control plane API and project-resolution checks are skipped intentionally. In that mode, focus on token, engine address, DNS, TLS or QUIC transport, and inventory checks.

The table output is useful for a human terminal:

rstream doctor

The JSON output is better for automation:

rstream doctor -o json | jq '.summary, .checks[] | select(.status != "pass")'

Missing engine

Commands that operate on the Engine API require an engine endpoint. When the engine is missing, the CLI returns an error indicating that an engine must be provided through a flag, an environment variable, or a selected context.

engine is required but not configured (set --engine or RSTREAM_ENGINE, or select a context via --context, RSTREAM_CONTEXT, or `rstream context use`)

For interactive use, select a project context with rstream project use <project-endpoint>. For stateless agents, set RSTREAM_ENGINE with either RSTREAM_AUTHENTICATION_TOKEN or the RSTREAM_MTLS_CERT_FILE / RSTREAM_MTLS_KEY_FILE pair before running the command.

rstream doctor -o json reports this as an engine_address skip or failure depending on the available context. If the context was expected to contain a project endpoint, inspect it with:

rstream context list -o json
rstream context get <name> -o json

Missing token

Commands that require Engine HTTP API authentication fail when no token is configured. In hosted workflows this is typically resolved by running rstream login. In project-scoped workflows this is resolved by providing a project-scoped token through a context or environment variables. mTLS client certificates authenticate the agent control channel, not the Engine HTTP API.

authentication is required but not configured (run rstream login, set RSTREAM_AUTHENTICATION_TOKEN, or set RSTREAM_MTLS_CERT_FILE and RSTREAM_MTLS_KEY_FILE)

The shortest hosted fix is rstream login. Automation that calls the Engine HTTP API stores a token in a dedicated context or sets RSTREAM_AUTHENTICATION_TOKEN.

For a developer machine, the normal recovery is:

rstream login
rstream project use <project-endpoint>

For a server, CI runner, or device, prefer a project-scoped context or environment variables:

rstream context create <name> \
  --engine <engine-host>:443 \
  --token-file /path/to/token \
  --default \
  --no-api-url

For commands that open an agent control channel, mTLS agent authentication can use a context with auth.mtls or the certificate and key files in the process environment:

RSTREAM_ENGINE="<engine-host>:443" \
RSTREAM_MTLS_CERT_FILE="/etc/rstream/client.pem" \
RSTREAM_MTLS_KEY_FILE="/etc/rstream/client-key.pem" \
rstream forward 8080

Do not set RSTREAM_AUTHENTICATION_TOKEN at the same time as the mTLS certificate and key variables; the CLI rejects that combination before connecting.

Expired token

When the CLI can decode the JWT expiration claim, it checks token expiration and returns an error when the token is expired.

token has expired (run rstream login or set RSTREAM_AUTHENTICATION_TOKEN)

Long-running automation rotates the stored credential or mints short-lived tokens from application credentials before starting the agent. Token families and reduction rules are documented in Tokens.

If an account-wide developer token expired, run rstream login again. If a project-scoped token expired, replace the token in the context or update RSTREAM_AUTHENTICATION_TOKEN.

Project resolution failures

Hosted contexts can store a project endpoint and resolve it into an engine address through the Control plane API. Resolution fails when the token cannot access the project, the project endpoint is wrong, the project belongs to another workspace, or the Control plane API cannot be reached.

rstream project list -o json
rstream project use <project-endpoint> -o json

If project use fails, inspect the authenticated account with rstream login and rstream project list -o json. Agents do not guess a different project when the task could affect billing, public exposure, or production traffic.

Engine reachability failures

When configuration and project resolution are valid but the engine cannot be reached, doctor usually isolates the failure to DNS, TLS or QUIC transport, or engine inventory.

DNS failures indicate that the engine host does not resolve from the current machine. TLS failures indicate that the host resolves but the TCP/TLS handshake does not complete with the expected server name. doctor probes TLS and QUIC independently, then reports the effective choice in tunnel_transport. A QUIC failure commonly means UDP is blocked by the local network, VPN, firewall, or proxy path. In auto, that failure is a fallback warning when TLS succeeds; in strict quic, it is fatal. Engine inventory failures indicate that the selected engine path is reachable but list calls were rejected or failed.

Use the engine and context values from rstream doctor -o json, then inspect runtime state:

rstream client list -o json
rstream tunnel list -o json

If both list commands fail while DNS and TLS pass, the token may lack engine permissions or may be scoped to a different project.

Tunnel does not appear

When rstream forward returns successfully, the tunnel becomes visible through the engine inventory. Use JSON output to capture the tunnel details directly from the command:

rstream forward 8080 -o json

If the command is running but the tunnel is not visible in the dashboard or CLI inventory, check the current context and list active tunnels:

rstream context get <name> -o json
rstream tunnel list -o json

The most common causes are a different default context, a token scoped to another project, the tunnel process exiting after startup, or a dashboard view opened on a different project.

Traffic does not route

A tunnel can be online while traffic still fails. In that case, separate the edge path from the local upstream path.

First, confirm the local service is reachable from the same machine that runs rstream forward:

curl -i http://127.0.0.1:<port>/

Then inspect tunnel state, hosted logs, and engine events. Hosted logs are better for request outcomes, firewall decisions, and routing failures. Engine events are better for client and tunnel lifecycle.

rstream tunnel list -o json
rstream events --transport websocket -o json

For HTTP tunnels with authentication, challenge mode, IP policy, GeoIP policy, or token access enabled, check the access policy before changing the upstream service.

Invalid signaling transport

The watch and events helpers accept sse and websocket transport values. Invalid values return a transport validation error.

Use the installed CLI help output to inspect the available event flags:

rstream events --help

For the raw engine endpoints and filtering model, see Signaling.

WebTTY is not visible

First decide which WebTTY surface you are troubleshooting. A lightweight WebTTY tunnel is visible only while the tunnel is online. A registered WebTTY server can remain visible while offline because the durable server record exists in the Control plane.

Dashboard sessions for a lightweight WebTTY tunnel require a published WebTTY server because the browser needs a wss:// entrypoint. A private --no-publish WebTTY server remains reachable through native rstream clients, but it will not provide the browser-facing endpoint used by the dashboard.

Start a dashboard-compatible server with:

rstream webtty server -v --rstream --name <machine-name>

Then inspect inventory:

rstream webtty list -o json
rstream tunnel list --filter 'labels.application-protocol=rstream.webtty' -o json

If the server appears in CLI inventory but not in the dashboard, confirm that the dashboard is opened on the same project and that the server is published. If neither inventory shows the server, check the server process logs and run rstream doctor -o json on the machine that starts WebTTY.

For registered servers, inspect the durable server record first:

rstream webtty server list -o json
rstream webtty server show <server-id>

If the registered server exists but is offline, check the service process and the associated live tunnel state. Registered server online state is derived from the runtime connection; there is no separate WebTTY liveness mechanism to repair.

WebTTY E2E trust fails

E2E failures fail closed. Do not work around them by removing encryption until the missing trust layer is understood.

For explicit-key E2E, the client must trust the WebTTY server endpoint identity before it sends terminal content. If the server requires client authentication, the client must also use a WebTTY identity whose signing key is authorized on that server:

rstream webtty known-server list
rstream webtty known-server add shell \
  --key '<server-endpoint-identity>' \
  --client-identity operator-device
rstream webtty identity show --name operator-device --endpoint-identity
rstream webtty authorized-client list --identity shell
rstream webtty authorized-client add operator-device --identity shell --key '<client-endpoint-identity>'

For workspace-managed E2E, the caller must be a trusted workspace browser or trusted workspace device. CLI, agent, and service devices are separate from browser trust:

rstream workspace device status
rstream workspace device enroll --kind cli --label operator-cli

These commands use the workspace from the active project context. If there is no active project context, run rstream workspace list and add --workspace <workspace-id>.

Workspace-managed E2E requires an Enterprise workspace with Workspace Protection enabled. A user can have normal project permissions and still fail to decrypt protected WebTTY content if the current browser or device is not trusted.

Agent and CI output

Automation uses JSON output and avoids parsing terminal table output. The most useful commands are:

rstream login -o json
rstream project use <project-endpoint> -o json
rstream context list -o json
rstream tunnel list -o json
rstream client list -o json
rstream webtty list -o json
rstream doctor -o json

Browser-based login progress and approval URLs may be written to stderr when JSON output is selected, so stdout remains machine-readable.