rathole-org/rathole · error
missing semicolon
Error message
missing semicolon
What it means
host_port_pair splits an `host:port` string at the last colon via rfind(':') and panics with "missing semicolon" if there is no colon. The panic means the address string passed to tcp_connect_with_proxy/connect lacked a port component.
Solutions
- Append the port to the address, e.g. `example.com:443`.
- Validate user-supplied addresses contain a `host:port` before passing them in.
- For IPv6 literals use bracketed form `[::1]:443` so the last-colon split is unambiguous.
- Consider using a parsing helper (SocketAddr::from_str) to get a proper error instead of a panic.
Example fix
// before let addr = "example.com"; // panics in host_port_pair // after let addr = "example.com:443";
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_host_port(s: &str) -> Result<(), String> {
match s.rfind(':') {
Some(i) if i + 1 < s.len() && s[i+1..].chars().all(|c| c.is_ascii_digit()) => Ok(()),
_ => Err(format!("address '{}' must be in host:port form", s)),
}
} Try / catch
std::panic::catch_unwind(|| host_port_pair(addr))
.and_then(|r| r)
.map_err(|_| anyhow!("address '{}' must include a port (host:port)", addr)); Prevention
- Always include the port in address configs
- Use bracketed [host]:port form for IPv6 literals
- Validate addresses at config-load time
When it happens
Trigger: Calling host_port_pair (via connect or tcp_connect_with_proxy) with an address string like "example.com" or "example.com." without `:port`.
Common situations: Users writing just a hostname in the config's remote_addr; shell/env interpolation dropping the `:port` suffix; copy-paste of a URL where the port got separated; IPv6 literals without brackets plus port, causing a malformed string.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
AI-assisted analysis of rathole-org/rathole@a292f7ed54 (2026-09-07).
Data as JSON: /api/errors/485b990a9b1f0c9e.
Report an issue: GitHub.
Appendix: source
Thrown at src/helper.rs:62
}
#[allow(dead_code)]
pub fn feature_neither_compile(feature1: &str, feature2: &str) -> ! {
panic!(
"Neither of the feature '{}' or '{}' is compiled in this binary. Please re-compile rathole",
feature1, feature2
)
}
pub async fn to_socket_addr<A: ToSocketAddrs>(addr: A) -> Result<SocketAddr> {
lookup_host(addr)
.await?
.next()
.ok_or_else(|| anyhow!("Failed to lookup the host"))
}
pub fn host_port_pair(s: &str) -> Result<(&str, u16)> {
let semi = s.rfind(':').expect("missing semicolon");
Ok((&s[..semi], s[semi + 1..].parse()?))
}
/// Create a UDP socket and connect to `addr`
pub async fn udp_connect<A: ToSocketAddrs>(addr: A, prefer_ipv6: bool) -> Result<UdpSocket> {
let (socket_addr, bind_addr);
match prefer_ipv6 {
false => {
socket_addr = to_socket_addr(addr).await?;
bind_addr = match socket_addr {
SocketAddr::V4(_) => "0.0.0.0:0",
SocketAddr::V6(_) => ":::0",
};
},
true => {View on GitHub (pinned to a292f7ed54)