shadowsocks/shadowsocks-rust · error
`forward_port` cannot be missing or 0
Error message
`forward_port` cannot be missing or 0
What it means
Raised under the `local-tunnel` feature when a local entry specifies `forward_address` (meaning it is a tunnel) but `forward_port` is either absent or 0. A tunnel target needs both a host and a non-zero port, so the config is rejected as Malformed.
Source
Thrown at crates/shadowsocks-service/src/config.rs:1935
None => {
// DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility
// see https://github.com/shadowsocks/shadowsocks-rust/issues/1281
let mode = match protocol {
#[cfg(feature = "local-dns")]
ProtocolType::Dns => Mode::TcpAndUdp,
_ => global_mode,
};
local_config.mode = mode;
}
}
#[cfg(feature = "local-tunnel")]
if let Some(forward_address) = local.forward_address {
let forward_port = match local.forward_port {
None | Some(0) => {
let err =
Error::new(ErrorKind::Malformed, "`forward_port` cannot be missing or 0", None);
return Err(err);
}
Some(p) => p,
};
local_config.forward_addr = Some(match forward_address.parse::<IpAddr>() {
Ok(ip) => Address::from(SocketAddr::new(ip, forward_port)),
Err(..) => Address::from((forward_address, forward_port)),
});
}
#[cfg(feature = "local-redir")]
if let Some(tcp_redir) = local.tcp_redir {
match tcp_redir.parse::<RedirType>() {
Ok(r) => local_config.tcp_redir = r,
Err(..) => {
let err = Error::new(ErrorKind::Malformed, "`tcp_redir` invalid", None);
return Err(err);View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Set `forward_port` to the target service's port (1-65535), e.g. 53 for DNS over the tunnel.
- Remove `forward_address` if a tunnel is not intended (also consider setting protocol to "tunnel" explicitly).
- Verify the config file actually contains forward_port — a JSON merge may have dropped it.
Example fix
// before
{ "protocol": "tunnel", "forward_address": "8.8.8.8" }
// after
{ "protocol": "tunnel", "forward_address": "8.8.8.8", "forward_port": 53 } Defensive patterns
Strategy: validation
Validate before calling
fn validate_tunnel_target(entry: &serde_json::Value) -> Result<(), String> {
if entry.get("forward_address").is_some() {
match entry.get("forward_port") {
None => return Err("forward_address set but forward_port missing".into()),
Some(p) if p.as_u64() == Some(0) => {
return Err("forward_port cannot be 0".into());
}
_ => {}
}
}
Ok(())
} Try / catch
match LocalConfig::load_from(config_path) {
Ok(cfg) => start(cfg),
Err(e) if e.to_string().contains("forward_port") => {
eprintln!("Set a real forward_port (1-65535) for the tunnel: {e}");
std::process::exit(1);
}
Err(e) => return Err(e.into()),
} Prevention
- Remember forward_address and forward_port are a mandatory pair for tunnels.
- Use the destination service's well-known port (53 for DNS, etc.).
- Validate tunnels before deploy: host present => port must be present and non-zero.
When it happens
Trigger: Enabling a tunnel local server with `"forward_address": "1.2.3.4"` but omitting `forward_port`, or setting `"forward_port": 0`.
Common situations: Tunnel configs copied from examples with the destination port stripped; user forgot the remote service port (e.g. forwarding to a DNS or game server); generated configs where the port variable was empty.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- missing `forward_addr` in configuration
- missing `local_port`
- `local_port` cannot be 0
- `local_udp_port` cannot be 0
- `server_port` shouldn't be 0
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/f2c435921656a908.
Report an issue: GitHub.