rathole-org/rathole · error

Missing tls config

Error message

Missing tls config

What it means

The native-tls transport wrapper requires TLS settings to operate. Its `new` constructor takes the `tls` section from TransportConfig, and if it is absent (`config.tls` is None) it returns this error from src/transport/native_tls.rs:32. TLS is not optional when this transport is selected.

Solutions

  1. Add the `[transport.tls]` section to your config with the required fields (certificate, private key, optionally trusted_root).
  2. Confirm the transport type you intend matches the config: either add tls config or switch to the plain TCP transport.
  3. Check the example configs in the repo for the exact key names (`tls.hostname`, `tls.cert`, etc.).
  4. Validate the config file was loaded from the path you think (watch for stale config copies).

Example fix

# before
[transport]
type = "tls"

# after
[transport]
type = "tls"
[transport.tls]
hostname = "example.com"
cert = "cert.pem"
key = "key.pem"
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("tls")).is_none() {
    anyhow::bail!("tls transport selected but [transport.tls] is missing");
}

Prevention

When it happens

Trigger: Configuring transport type to use native TLS but omitting the `[transport.tls]` block (certificate, key, trusted_root) from the config.

Common situations: Selecting the tls transport while copying a plain TCP example config; deleting the tls section during config refactors; version upgrades where the tls block moved under transport and the old location is ignored.

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/1028e84df2f1c983. Report an issue: GitHub.

Appendix: source

Thrown at src/transport/native_tls.rs:32

pub struct TlsTransport {
    tcp: TcpTransport,
    config: TlsConfig,
    connector: Option<TlsConnector>,
    tls_acceptor: Option<TlsAcceptor>,
}

#[async_trait]
impl Transport for TlsTransport {
    type Acceptor = TcpListener;
    type RawStream = TcpStream;
    type Stream = TlsStream<TcpStream>;

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

        let connector = match config.trusted_root.as_ref() {
            Some(path) => {
                let s = fs::read_to_string(path)
                    .with_context(|| "Failed to read the `tls.trusted_root`")?;
                let cert = Certificate::from_pem(s.as_bytes())
                    .with_context(|| "Failed to read certificate from `tls.trusted_root`")?;
                let connector = native_tls::TlsConnector::builder()
                    .add_root_certificate(cert)
                    .build()?;
                Some(TlsConnector::from(connector))
            }
            None => {
                // if no trusted_root is specified, allow TlsConnector to use system default
                let connector = native_tls::TlsConnector::builder().build()?;
                Some(TlsConnector::from(connector))
            }
        };

View on GitHub (pinned to a292f7ed54)