{"record":{"id":"0d2e33b80b85caf2","repo":"shadowsocks/shadowsocks-rust","slug":"failed-to-create-file-writer-for-logging","errorCode":null,"errorMessage":"Failed to create file writer for logging","messagePattern":"Failed to create file writer for logging","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/logging/tracing.rs","lineNumber":66,"sourceCode":"}\n\nimpl MakeLayer for LogConsoleWriterConfig {\n    fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer {\n        let level = self.level.unwrap_or(global.level);\n        let format = apply_override(&global.format, &self.format);\n        let ansi = io::stdout().is_terminal();\n        make_fmt_layer(bin_name, level, &format, ansi, io::stdout)\n    }\n}\n\nimpl MakeLayer for LogFileWriterConfig {\n    fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer {\n        let level = self.level.unwrap_or(global.level);\n        let format = apply_override(&global.format, &self.format);\n\n        let file_writer = make_file_writer(bin_name, self)\n            // don't have the room for a more graceful error handling here\n            .expect(\"Failed to create file writer for logging\");\n        make_fmt_layer(bin_name, level, &format, false, file_writer)\n    }\n}\n\n#[cfg(unix)]\nimpl MakeLayer for LogSyslogWriterConfig {\n    fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer {\n        let level = self.level.unwrap_or(global.level);\n        let format = apply_override(&global.format, &self.format);\n\n        let syslog_writer = make_syslog_writer(bin_name, self);\n        make_fmt_layer(bin_name, level, &format, false, syslog_writer)\n    }\n}\n\n/// Boilerplate for configuring a `fmt::Layer` with `level` and `format` for different writers.\nfn make_fmt_layer<W>(bin_name: &str, level: u32, format: &LogFormatConfig, ansi: bool, writer: W) -> BoxedLayer\nwhere","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/src/logging/tracing.rs#L48-L84","documentation":"Panic when the tracing-based logging subsystem cannot create the file writer for a file-logging layer in make_layer: make_file_writer(bin_name, self) returned Err (unwritable/missing directory, permission denied, disk error) and expect('Failed to create file writer for logging') panics, as noted by the inline comment about the lack of graceful handling.","triggerScenarios":"Configuring a file logger (LogConfig with file output / LogTracingFileConfig) where the log directory doesn't exist, is not writable, or a rotation path is invalid; make_layer then panics while assembling the layer stack.","commonSituations":"Daemon running as an unprivileged user with a log dir owned by root; misconfigured log-file path (relative path resolving under a read-only cwd); disk-full or deleted log directory at startup.","solutions":["Verify the log directory exists and is writable by the process user before startup","Use an absolute log file path in the config and create the directory in your launch script","Fall back to console logging if the file writer fails (patch or wrap make_layer)","Run as a user with correct permissions or adjust log-dir ownership"],"exampleFix":"// before\nlet file_writer = make_file_writer(bin_name, self)\n    .expect(\"Failed to create file writer for logging\");\n// after\nstd::fs::create_dir_all(&log_dir)?;\nlet file_writer = make_file_writer(bin_name, self)\n    .unwrap_or_else(|e| {\n        eprintln!(\"file logging disabled: {}\", e);\n        make_console_writer()\n    });","handlingStrategy":"fallback","validationCode":"fn ensure_log_dir_writable(dir: &Path) -> Result<(), String> {\n    std::fs::create_dir_all(dir).map_err(|e| format!(\"cannot create log dir {:?}: {}\", dir, e))?;\n    let probe = dir.join(\".write_probe\");\n    std::fs::write(&probe, b\"\").map_err(|e| format!(\"log dir {:?} not writable: {}\", dir, e))?;\n    let _ = std::fs::remove_file(&probe);\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// expect() panics; pre-flight the directory and fall back to console logging on failure\nlet file_writer = match make_file_writer(bin_name, self) {\n    Ok(w) => w,\n    Err(e) => { eprintln!(\"file logging unavailable: {}\", e); return make_console_layer(); }\n};","preventionTips":["Create the log directory in your service/launcher before starting the binary","Run the process with a user that owns the log directory","Use absolute log paths to survive daemonization cwd changes","Add a startup smoke test that writes and deletes a probe file in the log dir"],"tags":["rust","logging","tracing","file-io","panic"],"backgroundTag":"file-write-failed","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}