denoland/deno · error
failed to set otel globals
Error message
failed to set otel globals
What it means
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.
Source
Thrown at ext/telemetry/lib.rs:1423
let span_attribute_count_limit = span_attribute_count_limit_from_env(sys);
let span_attribute_value_length_limit =
span_attribute_value_length_limit_from_env(sys);
let sampler = Sampler::from_env(sys)?;
OTEL_GLOBALS
.set(OtelGlobals {
log_processor,
span_processor,
id_generator,
meter_provider,
builtin_instrumentation_scope,
span_event_count_limit,
span_attribute_count_limit,
span_attribute_value_length_limit,
sampler,
config,
})
.map_err(|_| deno_core::anyhow::anyhow!("failed to set otel globals"))?;
deno_signals::before_exit(before_exit);
deno_net::tunnel::disable_before_exit();
Ok(())
}
fn before_exit() {
log::trace!("deno_telemetry::before_exit");
let Some(OtelGlobals {
span_processor: spans,
log_processor: logs,
meter_provider,
..
}) = OTEL_GLOBALS.get()
else {
return;View on GitHub (pinned to 89f33cbef2)
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
Example fix
// before — two components each call init
/* component A */ deno_telemetry::init(opts_a)?;
/* component B */ deno_telemetry::init(opts_b)?; // Err: failed to set otel globals
// after — single guarded entry point
use std::sync::OnceLock;
static TELEMETRY_INIT: OnceLock<()> = OnceLock::new();
fn init_telemetry(opts: Options) -> anyhow::Result<()> {
if TELEMETRY_INIT.set(()).is_err() {
return Ok(()); // already initialized in this process
}
deno_telemetry::init(opts)
} Defensive patterns
Strategy: validation
Validate before calling
use std::sync::OnceLock;
static TELEMETRY_INIT: OnceLock<()> = OnceLock::new();
// route every caller through this instead of deno_telemetry::init
fn init_telemetry_once(opts: TelemetryOptions) -> anyhow::Result<()> {
if TELEMETRY_INIT.set(()).is_err() {
return Ok(()); // already initialized in this process
}
deno_telemetry::init(opts)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ${prefix}Linter plugin must be an object
- Invalid response
- vsock is not supported on this platform
- invalid vsock addr
- no private key found in OTEL_EXPORTER_OTLP_CLIENT_KEY file
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/bd632989637d482b.
Report an issue: GitHub.