shadowsocks/shadowsocks-rust · error
missing `forward_addr` in configuration
Error message
missing `forward_addr` in configuration
What it means
During Config::validate() for a local server with ProtocolType::Tunnel (the port-forwarding/tunnel local), the `forward_addr` field must be set. If it is None, the config is rejected with ErrorKind::MissingField. A tunnel without a forward address has nowhere to relay traffic, so the library refuses to start it.
Source
Thrown at crates/shadowsocks-service/src/config.rs:1354
}
}
match self.protocol {
#[cfg(feature = "local-dns")]
ProtocolType::Dns => {
if self.local_dns_addr.is_none() || self.remote_dns_addr.is_none() {
let err = Error::new(
ErrorKind::MissingField,
"missing `local_dns_addr` or `remote_dns_addr` in configuration",
None,
);
return Err(err);
}
}
#[cfg(feature = "local-tunnel")]
ProtocolType::Tunnel => {
if self.forward_addr.is_none() {
let err = Error::new(ErrorKind::MissingField, "missing `forward_addr` in configuration", None);
return Err(err);
}
}
#[cfg(feature = "local-http")]
ProtocolType::Http => {
if !self.mode.enable_tcp() {
let err = Error::new(ErrorKind::Invalid, "TCP mode have to be enabled for http", None);
return Err(err);
}
}
_ => {}
}
Ok(())
}
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Add `forward_addr` to the tunnel configuration (e.g. "forward_addr": "example.com:443").
- In code, set config.forward_addr = Some(...) before validating.
- If tunneling is not intended, switch the local protocol to socks/http/dns as appropriate.
Example fix
// before
{ "protocol": "tunnel", "local_addr": "0.0.0.0:8388" }
// after
{ "protocol": "tunnel", "local_addr": "0.0.0.0:8388", "forward_addr": "example.com:443" } Defensive patterns
Strategy: validation
Validate before calling
if cfg.protocol == ProtocolType::Tunnel && cfg.forward_addr.is_none() {
return Err("tunnel protocol requires `forward_addr`");
} Type guard
fn tunnel_addr_set(cfg: &Config) -> bool {
cfg.protocol != ProtocolType::Tunnel || cfg.forward_addr.is_some()
} Try / catch
match Config::load(path) {
Ok(cfg) => start(cfg),
Err(e) if e.to_string().contains("forward_addr") => eprintln!("tunnel config must set forward_addr"),
Err(e) => return Err(e),
} Prevention
- Always pair protocol=tunnel with forward_addr in templates.
- Validate configs in CI before deploying.
- Document the required fields per protocol.
When it happens
Trigger: Calling Config::validate() (directly or via Config::load) when config_type is Local, protocol is ProtocolType::Tunnel, and forward_addr is None.
Common situations: A JSON config with "protocol": "tunnel" but no "forward_addr" key; programmatically built configs missing the forward_addr setter; copying a tunnel config from an example and deleting the destination address.
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 `local_dns_addr` or `remote_dns_addr` in configurati
- missing `local_port`
- `forward_port` cannot be missing or 0
- `password` is required
- missing `manager_port`
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/c6e68b832360fa22.
Report an issue: GitHub.