0x192/universal-android-debloater · error
setup logging
Error message
setup logging
What it means
This panic comes from `.expect("setup logging")` on the `Result<(), fern::InitError>` returned by `setup_logger()`. The fern crate returns `InitError` (typically `SetLoggerError`) when `fern::Dispatch::apply()` finds that a global logger has already been installed — the `log` crate only allows one logger per process. `setup_uad_dir` in the SOURCE could also fail indirectly: if the config/cache directory can't be resolved or created, `static` initialization panics before `setup_logger` even runs.
Source
Thrown at src/main.rs:25
colors::{Color, ColoredLevelConfig},
FormatCallback,
};
use log::Record;
use static_init::dynamic;
use std::path::PathBuf;
use std::{fmt::Arguments, fs::OpenOptions};
mod core;
mod gui;
#[dynamic]
static CONFIG_DIR: PathBuf = setup_uad_dir(dirs::config_dir());
#[dynamic]
static CACHE_DIR: PathBuf = setup_uad_dir(dirs::cache_dir());
fn main() -> iced::Result {
setup_logger().expect("setup logging");
gui::UadGui::start()
}
pub fn setup_logger() -> Result<(), fern::InitError> {
let colors = ColoredLevelConfig::new().info(Color::Green);
let make_formatter = |use_colors: bool| {
move |out: FormatCallback, message: &Arguments, record: &Record| {
out.finish(format_args!(
"{} {} [{}:{}] {}",
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
if use_colors {
format!("{:5}", colors.color(record.level()))
} else {
format!("{:5}", record.level().to_string())
},
record.file().unwrap_or("?"),
record.line().map(|l| l.to_string()).unwrap_or_default(),View on GitHub (pinned to 11f27c671c)
Solutions
- Ensure `setup_logger()` is called exactly once per process, early in `main` before any other crate initializes a logger
- Guard the call: check `log::max_level()` is `Off` / use a `OnceLock`/`std::sync::Once` so repeat invocations are no-ops
- Check no dependency or module calls `log::set_logger` / installs env_logger or a tracing-log bridge before this point
- In tests, don't call `setup_logger()` — or wrap it so it tolerates `SetLoggerError` and continues
- If the failure is the static `CONFIG_DIR` init (dirs returning None), fix XDG_CONFIG_HOME/XDG_CACHE_HOME or HOME env vars and directory permissions so `dirs::config_dir()/cache_dir()` return Some
Example fix
// before
fn main() -> iced::Result {
setup_logger().expect("setup logging");
gui::UadGui::start()
}
// after
fn main() -> iced::Result {
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| {
if let Err(e) = setup_logger() {
eprintln!("logging init failed: {e}"); // continue without logging
}
});
gui::UadGui::start()
} Defensive patterns
Strategy: fallback
Validate before calling
fn can_init_logger() -> bool {
// log crate: a logger is only settable once; probe cheap state first
std::env::var("NO_LOG").is_err()
}
if can_init_logger() { let _ = setup_logger(); } Type guard
fn logger_initialized() -> bool {
use log::LevelFilter;
log::max_level() != LevelFilter::Off
} Try / catch
match setup_logger() {
Ok(()) => {},
Err(fern::InitError::SetLoggerError(_)) => { /* logger already set; proceed */ },
Err(e) => eprintln!("failed to init logging: {e}"),
} Prevention
- Call logger setup only once, at the top of `main`, guarded by `std::sync::Once` or `OnceLock`
- Prefer `if let Err(e) = setup_logger()` or a `.unwrap_or_else` with eprintln over `.expect(...)` so a duplicate-logger error never aborts the GUI
- Don't install loggers in library code or unit tests; keep them in the binary entry point
- Keep `setup_uad_dir` for statics free of `.expect()`-heavy work, and validate XDG/HOME env vars in deployment scripts
When it happens
Trigger: Calling `setup_logger()` twice (e.g. once in main, once in a library/test init, or when the app is relaunched inside the same process); another logger (env_logger, tracing's log bridge, test harness) already registered a logger via `log::set_logger` before this call; in tests, Rust's libtest installs its own logger, making `apply()` fail.
Common situations: Running the GUI binary under a test harness or embedding UAD as a library where another crate already initialized logging; duplicate logger setup added accidentally in a refactor; calling `main`'s setup path again during in-process restarts.
Related errors
- Could not write config file to disk!
- Unable to parse backup file
- response should be Ok type
- Unable to write file
- Unable to parse
AI-assisted analysis of 0x192/universal-android-debloater@11f27c671c (2026-09-02).
Data as JSON: /api/errors/7ab01f0ad3a2b7de.
Report an issue: GitHub.