rathole-org/rathole · error

Missing websocket config

Error message

Missing websocket config

What it means

The websocket transport requires a `[transport.websocket]` section (which also decides whether TLS is used underneath). When `config.websocket` is None, the constructor at src/transport/websocket.rs:195 returns this error. Without it the transport cannot know the websocket path, headers, or TLS mode.

Solutions

  1. Add a `[transport.websocket]` section to the config (including `tls = true/false` and any path/header settings).
  2. If websocket is unnecessary, switch transport type to tcp or tls instead.
  3. Verify the exact field names against the repository's example websocket config.
  4. Re-check that the runtime config path points to the updated file.

Example fix

# before
[transport]
type = "websocket"

# after
[transport]
type = "websocket"
[transport.websocket]
tls = true
path = "/ws"
Defensive patterns

Strategy: validation

Validate before calling

let raw = std::fs::read_to_string(config_path)?;
let cfg: toml::Value = toml::from_str(&raw)?;
if cfg.get("transport").and_then(|t| t.get("websocket")).is_none() {
    anyhow::bail!("websocket transport requires [transport.websocket] in config");
}

Prevention

When it happens

Trigger: Setting transport type to websocket while omitting the websocket section from TransportConfig.

Common situations: Migrating from tcp/tls to websocket transport without updating the config; a reverse-proxy deployment where users forget the websocket-specific keys; configs edited by hand that dropped the websocket table.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of rathole-org/rathole@a292f7ed54 (2026-09-07). Data as JSON: /api/errors/ac799e9ec2fde694. Report an issue: GitHub.

Appendix: source

Thrown at src/transport/websocket.rs:195

}

#[derive(Debug)]
pub struct WebsocketTransport {
    sub: SubTransport,
    conf: WebSocketConfig,
}

#[async_trait]
impl Transport for WebsocketTransport {
    type Acceptor = TcpListener;
    type RawStream = TcpStream;
    type Stream = WebsocketTunnel;

    fn new(config: &TransportConfig) -> anyhow::Result<Self> {
        let wsconfig = config
            .websocket
            .as_ref()
            .ok_or_else(|| anyhow!("Missing websocket config"))?;

        let conf = WebSocketConfig {
            write_buffer_size: 0,
            ..WebSocketConfig::default()
        };
        let sub = match wsconfig.tls {
            true => SubTransport::Secure(TlsTransport::new(config)?),
            false => SubTransport::Insecure(TcpTransport::new(config)?),
        };
        Ok(WebsocketTransport { sub, conf })
    }

    fn hint(conn: &Self::Stream, opt: SocketOpts) {
        opt.apply(conn.inner.get_ref().inner.get_ref().get_tcpstream())
    }

    async fn bind<A: ToSocketAddrs + Send + Sync>(
        &self,

View on GitHub (pinned to a292f7ed54)