rathole-org/rathole · error
Expect UDP traffic. Please check the configuration.
Error message
Expect UDP traffic. Please check the configuration.
What it means
Mirror of the TCP case: the server sent DataChannelCmd::StartForwardUdp but the client's configured service is not UDP (it is TCP). run_data_channel bails because it cannot forward UDP datagrams through a TCP-configured local service. This always reflects a client/server config mismatch.
Solutions
- Align the service type to udp on both the client and server configs
- Confirm the local service really listens on UDP before declaring type = "udp"
- Restart both client and server after editing configs
Example fix
// before (server.toml) [server.services.ssh] bind_addr = "0.0.0.0:6022" type = "udp" // after [server.services.ssh] bind_addr = "0.0.0.0:6022" type = "tcp" # match the client's tcp local service
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the local service answers on UDP before declaring type = "udp":
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.settimeout(2)
try:
s.sendto(b'ping', ('127.0.0.1', 53)); s.recvfrom(512); print('UDP OK')
except OSError as e:
print('Not a UDP service:', e)
finally:
s.close() Prevention
- Set type = "udp" on BOTH client and server for UDP services
- Audit both TOML files together whenever service types change
- Restart both ends after changing service type so the tunnel renegotiates
When it happens
Trigger: Server sends DataChannelCmd::StartForwardUdp while the client's service entry has service_type != ServiceType::Udp (i.e. it is TCP).
Common situations: Exposing an SSH (TCP) service but the server-side service is declared with type = "udp"; typo'd or divergent TOML between the two ends of the tunnel.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Expect TCP traffic. Please check the configuration.
- Cannot determine running as a server or a client
- The token of service
- The feature ' ' is not compiled in this binary. Please…
- Neither of the feature
AI-assisted analysis of rathole-org/rathole@a292f7ed54 (2026-09-07).
Data as JSON: /api/errors/abe5983077125662.
Report an issue: GitHub.
Appendix: source
Thrown at src/client.rs:228
Ok(conn)
}
async fn run_data_channel<T: Transport>(args: Arc<RunDataChannelArgs<T>>) -> Result<()> {
// Do the handshake
let mut conn = do_data_channel_handshake(args.clone()).await?;
// Forward
match read_data_cmd(&mut conn).await? {
DataChannelCmd::StartForwardTcp => {
if args.service.service_type != ServiceType::Tcp {
bail!("Expect TCP traffic. Please check the configuration.")
}
run_data_channel_for_tcp::<T>(conn, &args.service.local_addr).await?;
}
DataChannelCmd::StartForwardUdp => {
if args.service.service_type != ServiceType::Udp {
bail!("Expect UDP traffic. Please check the configuration.")
}
run_data_channel_for_udp::<T>(conn, &args.service.local_addr, args.service.prefer_ipv6).await?;
}
}
Ok(())
}
// Simply copying back and forth for TCP
#[instrument(skip(conn))]
async fn run_data_channel_for_tcp<T: Transport>(
mut conn: T::Stream,
local_addr: &str,
) -> Result<()> {
debug!("New data channel starts forwarding");
let mut local = TcpStream::connect(local_addr)
.await
.with_context(|| format!("Failed to connect to {}", local_addr))?;View on GitHub (pinned to a292f7ed54)