denoland/deno · error · anyhow::Error
Invalid value for…
Error message
Invalid value for OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: {} What it means
When telemetry is enabled, Deno reads OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE to pick the metric temporality: 'cumulative' (default, also when unset), 'delta', or 'lowmemory'. The value is lowercased before matching, so case does not matter, but anything other than those three strings (after lowercasing) fails telemetry init.
Solutions
- Set the variable to cumulative, delta, or lowmemory (any case; exact spelling, no separator)
- Unset it to get cumulative
- Strip trailing newlines/whitespace when injecting via scripts: OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=$(printf %s "$v") or use tr -d '\n'
Example fix
# before export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=low_memory # -> Invalid value deno run --otel app.ts # after export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=lowmemory deno run --otel app.ts
Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = new Set(["cumulative", "delta", "lowmemory"]);
const pref = Deno.env.get("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE")?.toLowerCase().trim();
if (pref && !ALLOWED.has(pref)) {
throw new Error(`Temporality must be cumulative|delta|lowmemory, got '${pref}'`);
} Try / catch
const { code, stderr } = await new Deno.Command("deno", { args: ["run", "--otel", "app.ts"] }).output();
if (code !== 0 && new TextDecoder().decode(stderr).includes("TEMPORALITY_PREFERENCE")) {
delete env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE; // default cumulative
// relaunch
} Prevention
- Remember the spelling is 'lowmemory' — one word, no separator
- Trim command-substitution output: VALUE=$(printf %s "$(cat file)") to drop trailing newlines
- Centralize OTel env in a checked .env template
When it happens
Trigger: Running with --otel with the variable set to e.g. 'cumulative-delta', 'low_memory' (underscore instead of no separator), 'DELTA' works but ' delta' with internal space does not (only leading/trailing... note the value is not trimmed here, unlike OTEL_TRACES_SAMPLER), or other OTel-adjacent spellings.
Common situations: The spec name is 'lowmemory' (one word) but developers write 'low_memory' or 'low-memory'; CI injecting values with trailing newline from command substitution $(cat file); copying Prometheus-oriented config expecting 'delta' naming variants.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- Env var OTEL_EXPORTER_OTLP_PROTOCOL specifies an…
- Env var OTEL_TRACES_SAMPLER specifies an unsupported sampler
- Failed to read env var OTEL_EXPORTER_OTLP_PROTOCOL
- must be unset or set to 1
- failed to set otel globals
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/6958384bb9568b8d.
Report an issue: GitHub.
Appendix: source
Thrown at ext/telemetry/lib.rs:1311
format!("{}-{}", rt_config.runtime_version, sdk_version),
),
])
.build();
// The OTLP endpoint is automatically picked up from the
// `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable. Additional headers can
// be specified using `OTEL_EXPORTER_OTLP_HEADERS`.
let temporality_preference = sys
.env_var("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE")
.ok()
.map(|s| s.to_lowercase());
let temporality = match temporality_preference.as_deref() {
None | Some("cumulative") => Temporality::Cumulative,
Some("delta") => Temporality::Delta,
Some("lowmemory") => Temporality::LowMemory,
Some(other) => {
return Err(deno_core::anyhow::anyhow!(
"Invalid value for OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: {}",
other
));
}
};
let (span_processor, meter_provider, log_processor) = if use_console_exporter
{
let span_exporter = console_exporter::ConsoleSpanExporter::new();
let mut span_processor =
BatchSpanProcessor::builder(span_exporter, OtelSharedRuntime).build();
span_processor.set_resource(&resource);
let metric_exporter =
console_exporter::ConsoleMetricExporter::new(temporality);
let metric_reader = DenoPeriodicReader::new(sys, metric_exporter);
let meter_provider = SdkMeterProvider::builder()
.with_reader(metric_reader)View on GitHub (pinned to 9ad36f7a2c)