rathole-org/rathole · error

Missing TLS configuration

Error message

Missing TLS configuration

What it means

`transport_type = "tls"` was selected but the `[transport.tls]` section is absent from the config. The validator requires TLS settings whenever the TLS transport is chosen and fails fast with this error instead of failing later at connection time.

Solutions

  1. Add a `[transport.tls]` section with the required settings
  2. On the server add `pkcs12` (path to a .p12/.pkcs12 certificate) and `pkcs12_password`
  3. On the client set `tls_hostname` (and optionally `accept_invalid_certs` for self-signed certs)
  4. Check the section is nested correctly as `[transport.tls]`, not a top-level `[tls]` table

Example fix

# before
[transport]
type = "tls"

# after
[transport]
type = "tls"

[transport.tls]
tls_hostname = "example.com"
Defensive patterns

Strategy: validation

Validate before calling

let raw: toml::Value = toml::from_str(&cfg)?;
let ttype = raw["transport"]["type"].as_str().unwrap_or("tcp");
if ttype == "tls" && raw["transport"]["tls"].is_none() {
    return Err("transport.type = tls requires a [transport.tls] section".into());
}

Prevention

When it happens

Trigger: Running with a config where `[transport]` has `type = "tls"` (or transport_type is set to TLS) but no `[transport.tls]` table defining `pkcs12`/`pkcs12_password` (server) or `tls_hostname`/`accept_invalid_certs` (client).

Common situations: Users switch the transport type from tcp to tls and forget to add the tls block; configs copied from a tcp example; a misnamed section like `[tls]` at the wrong nesting level so it isn't deserialized into `config.tls`.

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/4bfb7f7475ce345b. Report an issue: GitHub.

Appendix: source

Thrown at src/config.rs:311

    }

    fn validate_transport_config(config: &TransportConfig, is_server: bool) -> Result<()> {
        config
            .tcp
            .proxy
            .as_ref()
            .map_or(Ok(()), |u| match u.scheme() {
                "socks5" => Ok(()),
                "http" => Ok(()),
                _ => Err(anyhow!(format!("Unknown proxy scheme: {}", u.scheme()))),
            })?;
        match config.transport_type {
            TransportType::Tcp => Ok(()),
            TransportType::Tls => {
                let tls_config = config
                    .tls
                    .as_ref()
                    .ok_or_else(|| anyhow!("Missing TLS configuration"))?;
                if is_server {
                    tls_config
                        .pkcs12
                        .as_ref()
                        .and(tls_config.pkcs12_password.as_ref())
                        .ok_or_else(|| anyhow!("Missing `pkcs12` or `pkcs12_password`"))?;
                }
                Ok(())
            }
            TransportType::Noise => {
                // The check is done in transport
                Ok(())
            }
            TransportType::Websocket => Ok(()),
        }
    }

    pub async fn from_file(path: &Path) -> Result<Config> {

View on GitHub (pinned to a292f7ed54)