astral-sh/ruff · error
`initLogging` to only be called at most once.
Error message
`initLogging` to only be called at most once.
What it means
`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.
Source
Thrown at crates/ty_wasm/src/lib.rs:84
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}
/// Initializes the logger with the given log level.
///
/// ## Panics
/// If this function is called more than once.
#[wasm_bindgen(js_name = "initLogging")]
pub fn init_logging(level: LogLevel) {
console_log::init_with_level(level.into())
.expect("`initLogging` to only be called at most once.");
}
#[derive(Copy, Clone, Debug)]
#[wasm_bindgen]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
impl From<LogLevel> for log::Level {
fn from(level: LogLevel) -> Self {
match level {
LogLevel::Trace => log::Level::Trace,
LogLevel::Debug => log::Level::Debug,
LogLevel::Info => log::Level::Info,View on GitHub (pinned to 26f38c119c)
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.
Example fix
// before
import { initLogging, LogLevel } from './ty_wasm';
initLogging(LogLevel.Warn);
// on hot reload / rerun:
initLogging(LogLevel.Debug); // panics
// after
let initialized = false;
export function setup(level) {
if (!initialized) {
initLogging(level);
initialized = true;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// JS guard before calling
if (!globalThis.__tyLoggingInitialized) {
globalThis.__tyLoggingInitialized = true;
initLogging(LogLevel.Warn);
} Type guard
function canInitLogging() {
return typeof globalThis.__tyLoggingInitialized === 'undefined';
} Try / catch
try {
initLogging(LogLevel.Warn);
} catch (e) {
// logger already installed; tolerate repeated init attempts
console.debug('initLogging skipped:', e);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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`.
Related errors
- `initLogging` to only be called at most once.
- Flame layer to be created
- {err}
- extra use-def data should have been retained
- Expected a Title
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/890d83103078bff5.
Report an issue: GitHub.