rathole-org/rathole · error

No such a service

Error message

No such a service {}

What it means

Fires in do_control_channel_handshake when a client requests a control channel for a service whose digest is not present in the server's services map (services.read().await.get(&service_digest) returned None). It means the client named a service the server has no configuration for; the server sends Ack::ServiceNotExist back on the control connection and this error aborts the handshake for that connection.

Solutions

  1. Verify the service name on the client matches a [[server.services]] entry in the server's config
  2. Reload the server config so the requested service is registered before clients connect
  3. Check the client config was not pointed at the wrong server instance
  4. Log the requested service name to help the operator spot typos
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/server.rs:306 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at src/server.rs:306

    let mut nonce = vec![0u8; HASH_WIDTH_IN_BYTES];
    rand::thread_rng().fill_bytes(&mut nonce);

    // Send hello
    let hello_send = Hello::ControlChannelHello(
        protocol::CURRENT_PROTO_VERSION,
        nonce.clone().try_into().unwrap(),
    );
    conn.write_all(&bincode::serialize(&hello_send).unwrap())
        .await?;
    conn.flush().await?;

    // Lookup the service
    let service_config = match services.read().await.get(&service_digest) {
        Some(v) => v,
        None => {
            conn.write_all(&bincode::serialize(&Ack::ServiceNotExist).unwrap())
                .await?;
            bail!("No such a service {}", hex::encode(service_digest));
        }
    }
    .to_owned();

    let service_name = &service_config.name;

    // Calculate the checksum
    let mut concat = Vec::from(service_config.token.as_ref().unwrap().as_bytes());
    concat.append(&mut nonce);

    // Read auth
    let protocol::Auth(d) = read_auth(&mut conn).await?;

    // Validate
    let session_key = protocol::digest(&concat);
    if session_key != d {
        conn.write_all(&bincode::serialize(&Ack::AuthFailed).unwrap())
            .await?;

View on GitHub (pinned to a292f7ed54)