shadowsocks/shadowsocks-rust · error
missing `local_dns_addr` or `remote_dns_addr` in configurati
Error message
missing `local_dns_addr` or `remote_dns_addr` in configuration
What it means
During Config::validate() for a local server with ProtocolType::Dns (the local DNS forwarder), the library requires both `local_dns_addr` and `remote_dns_addr` to be set. If either is absent, the configuration is rejected with ErrorKind::MissingField before the DNS local can start. This guard prevents a DNS protocol local from running with no upstream/downstream address to forward between.
Source
Thrown at crates/shadowsocks-service/src/config.rs:1343
fn check_integrity(&self) -> Result<(), Error> {
match self.protocol {
#[cfg(feature = "local-tun")]
ProtocolType::Tun => {}
_ => {
if self.addr.is_none() {
let err = Error::new(ErrorKind::MissingField, "missing `addr` in configuration", None);
return Err(err);
}
}
}
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() {View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Add both `local_dns_addr` and `remote_dns_addr` to the configuration (e.g. "local_dns_addr": "127.0.0.1:53", "remote_dns_addr": "8.8.8.8:53").
- In code, set them via the config builder/API before calling validate(): config.local_dns_addr = Some(...); config.remote_dns_addr = Some(...).
- If DNS forwarding is not needed, change the local protocol to one that does not require these fields (e.g. socks/http).
Example fix
// before
{ "protocol": "dns", "local_addr": "127.0.0.1:1080" }
// after
{ "protocol": "dns", "local_addr": "127.0.0.1:1080", "local_dns_addr": "127.0.0.1:53", "remote_dns_addr": "8.8.8.8:53" } Defensive patterns
Strategy: validation
Validate before calling
if cfg.protocol == ProtocolType::Dns && (cfg.local_dns_addr.is_none() || cfg.remote_dns_addr.is_none()) {
return Err("dns protocol requires both `local_dns_addr` and `remote_dns_addr`");
} Type guard
fn dns_addrs_set(cfg: &Config) -> bool {
cfg.protocol != ProtocolType::Dns || (cfg.local_dns_addr.is_some() && cfg.remote_dns_addr.is_some())
} Try / catch
match Config::load(path) {
Ok(cfg) => start(cfg),
Err(e) if e.to_string().contains("local_dns_addr") => eprintln!("add local_dns_addr/remote_dns_addr to config"),
Err(e) => return Err(e),
} Prevention
- Use a JSON schema or serde default checks to require both fields when protocol == dns.
- Lint example configs for protocol-specific required fields.
- Call Config::validate() in tests with your shipped configs.
When it happens
Trigger: Calling Config::validate() (or loading a config file via Config::load and then validating) where config_type is Local, protocol is ProtocolType::Dns, and either local_dns_addr or remote_dns_addr is None in the ServerConfig/config.
Common situations: Writing a JSON config with "protocol": "dns" but forgetting the "local_dns_addr" or "remote_dns_addr" keys; generating configs programmatically via ConfigBuilder and never calling the corresponding setters; upgrading from an older config format that lacked the DNS address fields.
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_dns_address` invalid
- `password` is required
- missing `manager_port`
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/f091e5fa23060742.
Report an issue: GitHub.