rathole-org/rathole · error
Protocol version mismatched. Expected
Error message
Protocol version mismatched. Expected {}, got {}. Please update `rathole`. What it means
read_hello deserializes the peer's hello message and checks the embedded protocol version against CURRENT_PROTO_VERSION. When a ControlChannelHello carries a different version, it bails because control-channel peers must speak the same protocol. This guards against incompatible client/server builds.
Solutions
- Upgrade the older side: rebuild/update rathole on both client and server to the same version
- Pin matching versions (same release) on both ends of the tunnel
- Check rathole --version on both ends and align before restarting
- If upgrading is impossible, use compatible release channels on both sides
Example fix
// before $ client: rathole v0.4.8 ↔ server: rathole v0.5.0 → version mismatch // after $ cargo install rathole # same latest version on both hosts $ client: rathole v0.5.0 ↔ server: rathole v0.5.0
Defensive patterns
Strategy: retry
Validate before calling
// Check version parity before connecting: $ rathole --version $ ssh server 'rathole --version' // Both must print the same version.
Try / catch
// Retry with backoff only after fixing versions; a version mismatch never heals on retry:
match client_connect().await {
Err(e) if e.to_string().contains("Protocol version mismatched") => {
eprintln!("Upgrade both rathole ends to the same version, then restart");
std::process::exit(1);
}
Err(e) => { /* transient error: retry with backoff */ }
Ok(v) => v,
} Prevention
- Upgrade client and server together in one maintenance window
- Pin the same rathole version in all Dockerfiles and package installs
- Run rathole --version on both ends as a deploy checklist step
When it happens
Trigger: Connecting a rathole client to a server built from a different (older or newer) version; the ControlChannelHello variant's version field differs from CURRENT_PROTO_VERSION in read_hello.
Common situations: Upgrading the server binary but not the client (or vice versa); a distro package pinned to an old rathole release talking to a recent server; cached old binaries in Docker images.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unexpected type of hello
- 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/f9908a928fc7e223.
Report an issue: GitHub.
Appendix: source
Thrown at src/protocol.rs:188
}
}
}
lazy_static! {
static ref PACKET_LEN: PacketLength = PacketLength::new();
}
pub async fn read_hello<T: AsyncRead + AsyncWrite + Unpin>(conn: &mut T) -> Result<Hello> {
let mut buf = vec![0u8; PACKET_LEN.hello];
conn.read_exact(&mut buf)
.await
.with_context(|| "Failed to read hello")?;
let hello = bincode::deserialize(&buf).with_context(|| "Failed to deserialize hello")?;
match hello {
Hello::ControlChannelHello(v, _) => {
if v != CURRENT_PROTO_VERSION {
bail!(
"Protocol version mismatched. Expected {}, got {}. Please update `rathole`.",
CURRENT_PROTO_VERSION,
v
);
}
}
Hello::DataChannelHello(v, _) => {
if v != CURRENT_PROTO_VERSION {
bail!(
"Protocol version mismatched. Expected {}, got {}. Please update `rathole`.",
CURRENT_PROTO_VERSION,
v
);
}
}
}
Ok(hello)View on GitHub (pinned to a292f7ed54)