{"record":{"id":"890d83103078bff5","repo":"astral-sh/ruff","slug":"initlogging-to-only-be-called-at-most-once-890d83","errorCode":null,"errorMessage":"`initLogging` to only be called at most once.","messagePattern":"`initLogging` to only be called at most once\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_wasm/src/lib.rs","lineNumber":84,"sourceCode":"\n    // When the `console_error_panic_hook` feature is enabled, we can call the\n    // `set_panic_hook` function at least once during initialization, and then\n    // we will get better error messages if our code ever panics.\n    //\n    // For more details see\n    // https://github.com/rustwasm/console_error_panic_hook#readme\n    #[cfg(feature = \"console_error_panic_hook\")]\n    console_error_panic_hook::set_once();\n}\n\n/// Initializes the logger with the given log level.\n///\n/// ## Panics\n/// If this function is called more than once.\n#[wasm_bindgen(js_name = \"initLogging\")]\npub fn init_logging(level: LogLevel) {\n    console_log::init_with_level(level.into())\n        .expect(\"`initLogging` to only be called at most once.\");\n}\n\n#[derive(Copy, Clone, Debug)]\n#[wasm_bindgen]\npub enum LogLevel {\n    Trace,\n    Debug,\n    Info,\n    Warn,\n    Error,\n}\n\nimpl From<LogLevel> for log::Level {\n    fn from(level: LogLevel) -> Self {\n        match level {\n            LogLevel::Trace => log::Level::Trace,\n            LogLevel::Debug => log::Level::Debug,\n            LogLevel::Info => log::Level::Info,","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ty_wasm/src/lib.rs#L66-L102","documentation":"`initLogging` is the wasm-bindgen entry point that installs the console logger for the ty WASM build via `console_log::init_with_level`. The underlying logger can only be installed once per WASM instance, so calling `initLogging` a second time makes `init_with_level` return `Err`, and the `.expect` turns that into a panic with this message.","triggerScenarios":"Calling `initLogging(level)` from JavaScript more than once on the same module instance — e.g. calling it on every effect or page-load handler, on hot-reload, or from both an app bootstrap and a test harness — without reinstantiating the WASM module.","commonSituations":"React StrictMode double-invoking effects in development, HMR re-running setup code, integration tests initializing logging per test while reusing one module, or a library consumer and the app both calling `initLogging`.","solutions":["Call `initLogging` exactly once, at the earliest application bootstrap point, before any other ty_wasm call.","Guard the call site in JS with a module-level `let loggingInitialized` flag so repeat calls are skipped.","Wrap the call in try/catch for idempotent best-effort initialization, tolerating the already-initialized error.","Recreate/reload the WASM module if a different log level is genuinely needed."],"exampleFix":"// before\nimport { initLogging, LogLevel } from './ty_wasm';\ninitLogging(LogLevel.Warn);\n// on hot reload / rerun:\ninitLogging(LogLevel.Debug); // panics\n\n// after\nlet initialized = false;\nexport function setup(level) {\n  if (!initialized) {\n    initLogging(level);\n    initialized = true;\n  }\n}","handlingStrategy":"try-catch","validationCode":"// JS guard before calling\nif (!globalThis.__tyLoggingInitialized) {\n  globalThis.__tyLoggingInitialized = true;\n  initLogging(LogLevel.Warn);\n}","typeGuard":"function canInitLogging() {\n  return typeof globalThis.__tyLoggingInitialized === 'undefined';\n}","tryCatchPattern":"try {\n  initLogging(LogLevel.Warn);\n} catch (e) {\n  // logger already installed; tolerate repeated init attempts\n  console.debug('initLogging skipped:', e);\n}","preventionTips":["Initialize logging once in the app entry point, not in components or per-test setup.","Account for React StrictMode double-effect invocation in development.","Use a module-level boolean or singleton wrapper around initLogging.","On HMR, guard initialization with module hot-accept state or dispose handlers."],"tags":["wasm","javascript","logging","panic","double-initialization"],"backgroundTag":"logger-already-initialized","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}