shadowsocks/shadowsocks-rust · error
missing `locals` for client configuration
Error message
missing `locals` for client configuration
What it means
ServiceConfig::check_integrity verifies that all fields required for the configured config_type are present. When config_type is a local (client) type but the locals list is empty, this Error with ErrorKind::MissingField is returned: a shadowsocks client needs at least one local listener to serve.
Source
Thrown at crates/shadowsocks-service/src/config.rs:2853
}
/// Check if there are any plugin are enabled with servers
pub fn has_server_plugins(&self) -> bool {
for inst in &self.server {
let server = &inst.config;
if server.plugin().is_some() {
return true;
}
}
false
}
/// Check if all required fields are already set
pub fn check_integrity(&self) -> Result<(), Error> {
if self.config_type.is_local() {
if self.local.is_empty() {
let err = Error::new(
ErrorKind::MissingField,
"missing `locals` for client configuration",
None,
);
return Err(err);
}
for local_config in &self.local {
local_config.config.check_integrity()?;
}
// Balancer related checks
if let Some(rtt) = self.balancer.max_server_rtt
&& rtt.as_secs() == 0
{
let err = Error::new(ErrorKind::Invalid, "balancer.max_server_rtt must be > 0", None);
return Err(err);
}View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Add at least one entry to the locals array in the config (e.g. a socks5 or http listener with address and port).
- Ensure you are running the client (sslocal) with a client config, not the server config file.
- If building Config in code, call config.local.push(LocalConfig::new(...)) before check_integrity().
- Verify config_type is set to Local and matches the binary you are launching.
Example fix
// before
{ "locals": [] }
// after
{ "locals": [ { "type": "socks", "addr": "127.0.0.1", "port": 1080 } ] } Defensive patterns
Strategy: validation
Validate before calling
fn validate_client_config(cfg: &Config) -> Result<(), String> {
if cfg.config_type.is_local() && cfg.local.is_empty() {
return Err("client config requires at least one entry in 'locals'".into());
}
Ok(())
} Type guard
fn has_local_listeners(cfg: &Config) -> bool {
!cfg.config_type.is_local() || !cfg.local.is_empty()
} Try / catch
match service_config.check_integrity() {
Ok(()) => { /* start client */ }
Err(e) if e.to_string().contains("missing `locals`") => {
log::error!("client config has no locals: add a socks/http listener");
}
Err(e) => log::error!("config integrity check failed: {e}"),
} Prevention
- Always define at least one local listener (socks/http) for client (sslocal) configs
- Do not reuse a server (ssserver) config file for the client binary
- Validate the config JSON schema before loading it in production
- Run check_integrity() early in your own code with a clear error message
When it happens
Trigger: Calling check_integrity() on a client-type Config after loading/compiling, with Config.local empty — e.g. a config JSON that only sets server addresses and method/password but defines no local listeners (locals array empty or absent).
Common situations: Using a server config file with a client binary (sslocal), copying a config template that omits the locals section, or programmatically constructing Config without pushing entries into local.
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
- `protocol` invalid
- invalid `mode`
- `server`, `server_port`, `method`, `password` must be provid
- balancer.max_server_rtt must be > 0
- server method doesn't support Extended Identity Header (EIH)
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/04bcb61fe2d42f5a.
Report an issue: GitHub.