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

  1. Add at least one entry to the locals array in the config (e.g. a socks5 or http listener with address and port).
  2. Ensure you are running the client (sslocal) with a client config, not the server config file.
  3. If building Config in code, call config.local.push(LocalConfig::new(...)) before check_integrity().
  4. 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

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


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/04bcb61fe2d42f5a. Report an issue: GitHub.