{"record":{"id":"bd632989637d482b","repo":"denoland/deno","slug":"failed-to-set-otel-globals","errorCode":null,"errorMessage":"failed to set otel globals","messagePattern":"failed to set otel globals","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ext/telemetry/lib.rs","lineNumber":1423,"sourceCode":"  let span_attribute_count_limit = span_attribute_count_limit_from_env(sys);\n  let span_attribute_value_length_limit =\n    span_attribute_value_length_limit_from_env(sys);\n  let sampler = Sampler::from_env(sys)?;\n\n  OTEL_GLOBALS\n    .set(OtelGlobals {\n      log_processor,\n      span_processor,\n      id_generator,\n      meter_provider,\n      builtin_instrumentation_scope,\n      span_event_count_limit,\n      span_attribute_count_limit,\n      span_attribute_value_length_limit,\n      sampler,\n      config,\n    })\n    .map_err(|_| deno_core::anyhow::anyhow!(\"failed to set otel globals\"))?;\n\n  deno_signals::before_exit(before_exit);\n  deno_net::tunnel::disable_before_exit();\n\n  Ok(())\n}\n\nfn before_exit() {\n  log::trace!(\"deno_telemetry::before_exit\");\n\n  let Some(OtelGlobals {\n    span_processor: spans,\n    log_processor: logs,\n    meter_provider,\n    ..\n  }) = OTEL_GLOBALS.get()\n  else {\n    return;","sourceCodeStart":1405,"sourceCodeEnd":1441,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/telemetry/lib.rs#L1405-L1441","documentation":"deno_telemetry::init installs process-wide state (OtelGlobals) into a OnceCell. If the cell is already occupied — init ran twice in the same process — set() returns the previous value and this generic error is raised. It is an internal invariant violation, not a user configuration problem.","triggerScenarios":"Embedders or internal code paths invoking deno_telemetry::init more than once per process, e.g. CLI startup init plus an extension or test harness that also initializes telemetry.","commonSituations":"Custom embedders building on deno_runtime/deno_telemetry; test harnesses that bring telemetry up per test case in one process; refactors that moved init into a shared helper called from two places.","solutions":["Initialize telemetry exactly once per process — guard the call site behind a OnceLock or AtomicBool","In test harnesses, run telemetry-dependent cases in separate processes","If hit with plain `deno` CLI commands and no custom embedding, report it as a Deno bug in init ordering"],"exampleFix":"// before — two components each call init\n/* component A */ deno_telemetry::init(opts_a)?;\n/* component B */ deno_telemetry::init(opts_b)?; // Err: failed to set otel globals\n\n// after — single guarded entry point\nuse std::sync::OnceLock;\nstatic TELEMETRY_INIT: OnceLock<()> = OnceLock::new();\nfn init_telemetry(opts: Options) -> anyhow::Result<()> {\n  if TELEMETRY_INIT.set(()).is_err() {\n    return Ok(()); // already initialized in this process\n  }\n  deno_telemetry::init(opts)\n}","handlingStrategy":"validation","validationCode":"use std::sync::OnceLock;\nstatic TELEMETRY_INIT: OnceLock<()> = OnceLock::new();\n\n// route every caller through this instead of deno_telemetry::init\nfn init_telemetry_once(opts: TelemetryOptions) -> anyhow::Result<()> {\n  if TELEMETRY_INIT.set(()).is_err() {\n    return Ok(()); // already initialized in this process\n  }\n  deno_telemetry::init(opts)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Initialize telemetry in exactly one place in the process (main runtime setup)","Run telemetry-dependent test cases in separate processes","Treat this error under plain `deno` CLI usage as a bug to report — single init is an internal invariant"],"tags":["telemetry","otel","initialization","internal","invariant"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}