shadowsocks/shadowsocks-rust · error
logging
Error message
logging
What it means
Panic while building the log4rs Config object in init_with_config: the builder chain .build(...) returned Err (e.g. duplicate logger names or an invalid appender/logger setup) and expect('logging') panics. This is the first of the two expect calls, on config construction rather than initialization.
Source
Thrown at src/logging/log4rs.rs:67
let (l1, l2) = match debug_level {
0 => (LevelFilter::Info, LevelFilter::Off),
1 => (LevelFilter::Debug, LevelFilter::Off),
2 => (LevelFilter::Trace, LevelFilter::Off),
3 => (LevelFilter::Trace, LevelFilter::Debug),
_ => (LevelFilter::Off, LevelFilter::Trace),
};
let config = match debug_level {
0..=3 => logging_builder
.logger(Logger::builder().build(bin_name, l1))
.logger(Logger::builder().build("shadowsocks_rust", l1))
.logger(Logger::builder().build("shadowsocks", l1))
.logger(Logger::builder().build("shadowsocks_service", l1)),
_ => logging_builder,
}
.build(Root::builder().appender("console").build(l2))
.expect("logging");
log4rs::init_config(config).expect("logging");
}
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Ensure the programmatically built Config has unique logger and appender names
- Print/log the generated config on failure instead of a bare expect
- Validate the LogConfig inputs (level, format) before building the log4rs config
- Check shadowsocks-rust updates for changes in init_with_config's builder logic
Example fix
// before
.build(Root::builder().appender("console").build(l2))
.expect("logging");
// after
.build(Root::builder().appender("console").build(l2))
.unwrap_or_else(|e| {
eprintln!("invalid logging config: {}", e);
std::process::exit(1);
}) Defensive patterns
Strategy: fallback
Validate before calling
// ensure logger/appender names passed into the builder are unique before building assert_unique(&["shadowsocks_rust", "shadowsocks", "shadowsocks_service"]);
Try / catch
// build() returns Result and init_with_config expects it; wrap init in a fallible helper let config = builder.build(root).map_err(|e| LoggingInitError(e))?;
Prevention
- Keep logger names distinct from the root appender configuration
- Log the generated config contents when debugging logging init
- Initialize logging once, early in main, before spawning threads
- Test init_with_config with each supported log level/format combination
When it happens
Trigger: init_with_config constructs a Config with appenders/loggers whose names collide or are invalid, causing ConfigBuilder::build to error before log4rs::init_config is reached.
Common situations: Bin-name-derived logger names duplicating the root/other loggers; programmatic LogConfig values producing zero or conflicting appenders; refactors changing logger name strings (shadowsocks_rust, shadowsocks, shadowsocks_service) into collisions.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- init logging with file
- missing manager config
- Failed to create file writer for logging
- syslog identity contains null-byte ('\0')
- method
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/c8658e63f19951d2.
Report an issue: GitHub.