rathole-org/rathole · error
Unexpected type of hello
Error message
Unexpected type of hello
What it means
After connecting to the server, the client reads a hello message and expects ControlChannelHello; any other hello variant triggers this bail. It means the remote peer answered on the control channel with unexpected data — typically not a rathole server at all, or a version/protocol mismatch (though version mismatch has its own error).
Solutions
- Verify remote_addr points to the rathole server's control-channel port, not another service
- Confirm the server is actually running and reachable at that address
- Check for port conflicts — something else may be listening on the configured port
- Test with a raw connection (nc host port) to see what the endpoint responds with
Example fix
// before (client.toml) [client] remote_addr = "example.com:80" # wrong port, HTTP server answers // after [client] remote_addr = "example.com:2333" # rathole server's control port
Defensive patterns
Strategy: validation
Validate before calling
// Probe the endpoint before pointing rathole at it: nc -vz example.com 2333 && timeout 3 bash -c 'exec 3<>/dev/tcp/example.com/2333; head -c 64 <&3' | xxd | head // Non-rathole banner bytes mean wrong host/port.
Prevention
- Point remote_addr at the server's control port, never at other services on the host
- Confirm the server process is up (systemctl status rathole / docker ps)
- Use distinct ports for control and other daemons to avoid conflicts
When it happens
Trigger: read_hello returns a Hello variant that is not ControlChannelHello inside ControlChannel::run, immediately after TCP connect to remote_addr.
Common situations: remote_addr points at the wrong host or port (e.g. the HTTP port, an SSH daemon, or the rathole data port); a proxy or firewall returns a non-rathole banner; connecting a client to another client.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Protocol version mismatched. Expected
- Failed to lookup the host
- The feature ' ' is not compiled in this binary. Please…
- Neither of the feature
- Cannot determine running as a server or a client
AI-assisted analysis of rathole-org/rathole@a292f7ed54 (2026-09-07).
Data as JSON: /api/errors/bd2c600e586abbb3.
Report an issue: GitHub.
Appendix: source
Thrown at src/client.rs:429
.connect(&remote_addr)
.await
.with_context(|| format!("Failed to connect to {}", &self.remote_addr))?;
T::hint(&conn, SocketOpts::for_control_channel());
// Send hello
debug!("Sending hello");
let hello_send =
Hello::ControlChannelHello(CURRENT_PROTO_VERSION, self.digest[..].try_into().unwrap());
conn.write_all(&bincode::serialize(&hello_send).unwrap())
.await?;
conn.flush().await?;
// Read hello
debug!("Reading hello");
let nonce = match read_hello(&mut conn).await? {
ControlChannelHello(_, d) => d,
_ => {
bail!("Unexpected type of hello");
}
};
// Send auth
debug!("Sending auth");
let mut concat = Vec::from(self.service.token.as_ref().unwrap().as_bytes());
concat.extend_from_slice(&nonce);
let session_key = protocol::digest(&concat);
let auth = Auth(session_key);
conn.write_all(&bincode::serialize(&auth).unwrap()).await?;
conn.flush().await?;
// Read ack
debug!("Reading ack");
match read_ack(&mut conn).await? {
Ack::Ok => {}
v => {View on GitHub (pinned to a292f7ed54)