{"record":{"id":"d6665410db08ebe3","repo":"GraphiteEditor/Graphite","slug":"failed-to-set-logger","errorCode":null,"errorMessage":"Failed to set logger","messagePattern":"Failed to set logger","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/wrapper/src/lib.rs","lineNumber":47,"sourceCode":"pub static LOGGER: WasmLog = WasmLog;\n\nthread_local! {\n\t#[cfg(not(feature = \"native\"))]\n\tpub static EDITOR: Mutex<Option<editor::application::Editor>> = const { Mutex::new(None) };\n\t#[cfg(not(feature = \"native\"))]\n\tpub static MESSAGE_BUFFER: std::cell::RefCell<Vec<Message>> = const { std::cell::RefCell::new(Vec::new()) };\n\tpub static EDITOR_WRAPPER: Mutex<Option<editor_wrapper::EditorWrapper>> = const { Mutex::new(None) };\n\tpub static PANIC_DIALOG_MESSAGE_CALLBACK: std::cell::RefCell<Option<js_sys::Function>> = const { std::cell::RefCell::new(None) };\n}\n\n/// Initialize the backend\n#[wasm_bindgen(start)]\npub fn init_graphite() {\n\t// Set up the panic hook\n\tpanic::set_hook(Box::new(panic_hook));\n\n\t// Set up the logger with a default level of debug\n\tlog::set_logger(&LOGGER).expect(\"Failed to set logger\");\n\tlog::set_max_level(log::LevelFilter::Debug);\n}\n\n/// When a panic occurs, notify the user and log the error to the JS console before the backend dies\npub fn panic_hook(info: &panic::PanicHookInfo) {\n\tlet info = info.to_string();\n\n\t// Node graph panics can only originate here when the node graph runs inside this wasm module\n\t#[cfg(feature = \"editor\")]\n\t{\n\t\tlet backtrace = Error::new(\"stack\").stack().to_string();\n\t\tif backtrace.contains(\"DynAnyNode\") {\n\t\t\tlog::error!(\"Node graph evaluation panicked {info}\");\n\n\t\t\t// When the graph panics, the node runtime lock may not be released properly\n\t\t\tif editor::node_graph_executor::NODE_RUNTIME.try_lock().is_none() {\n\t\t\t\tunsafe { editor::node_graph_executor::NODE_RUNTIME.force_unlock() };\n\t\t\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/frontend/wrapper/src/lib.rs#L29-L65","documentation":"init_graphite (the #[wasm_bindgen(start)] entry) installs WasmLog as the process-wide logger via log::set_logger, which fails — and here panics — whenever a logger is already installed. The log crate permits exactly one global logger per process, so a second initialization or a competing logging crate trips this expect.","triggerScenarios":"init_graphite running twice, for example hot-module reload re-instantiating the wasm module or the module being imported by two bundles on one page; another crate (wasm_logger, console_log, tracing-wasm) claiming the logger before the wrapper's start function runs.","commonSituations":"Dev servers with HMR; embedding the editor wasm in multiple places on a page; mixing logging solutions across dependencies in the same binary.","solutions":["Treat the failure as benign: if log::set_logger errors, a logger is already installed and initialization can continue","Guard installation with std::sync::Once so repeated init_graphite calls are no-ops","Audit the dependency tree for other logger crates initialized at startup and remove the duplicate"],"exampleFix":"// before\nlog::set_logger(&LOGGER).expect(\"Failed to set logger\");\n\n// after\nstatic LOG_INIT: std::sync::Once = std::sync::Once::new();\nLOG_INIT.call_once(|| {\n\tlet _ = log::set_logger(&LOGGER);\n});\nlog::set_max_level(log::LevelFilter::Debug);","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match log::set_logger(&LOGGER) {\n\tOk(()) => {}\n\tErr(_already_set) => debug!(\"a logger is already installed; keeping it\"),\n}","preventionTips":["Initialize logging exactly once per process; wrap the call in std::sync::Once","Avoid linking two logger backends in one wasm binary","Configure the dev server to fully reload on wasm changes so HMR cannot double-instantiate the module"],"tags":["log","wasm","initialization","hmr"],"backgroundTag":"logger-already-initialized","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}