linera-io/linera-protocol · error
Failed to create OTLP exporter
Error message
Failed to create OTLP exporter
What it means
The linera-service tracing initializer builds an OpenTelemetry OTLP span exporter (gRPC/tonic transport) from an endpoint taken from the `otlp_endpoint` parameter or the LINERA_OTLP_EXPORTER_ENDPOINT environment variable. `SpanExporter::builder().with_tonic().with_endpoint(endpoint).build()` returns a Result because it parses and validates the endpoint URL and exporter configuration, and `.expect("Failed to create OTLP exporter")` crashes the process during tracing init when construction fails. It can only fire when OTLP is explicitly enabled: with no endpoint configured, init() falls back to the plain non-OTLP initializer and returns early.
Source
Thrown at linera-service/src/tracing/opentelemetry.rs:151
Some(ep) if !ep.is_empty() => ep.to_string(),
_ => match std::env::var("LINERA_OTLP_EXPORTER_ENDPOINT") {
Ok(ep) if !ep.is_empty() => ep,
_ => {
crate::tracing::init(log_name);
return;
}
},
};
let resource = Resource::builder()
.with_service_name(log_name.to_string())
.build();
let exporter = SpanExporter::builder()
.with_tonic()
.with_endpoint(endpoint)
.build()
.expect("Failed to create OTLP exporter");
// Configure batch processor for high-throughput scenarios
// Larger queue (16k instead of 2k default) to handle benchmark load
// Faster export (100ms instead of 5s default) to prevent queue buildup
let batch_config = opentelemetry_sdk::trace::BatchConfigBuilder::default()
.with_max_queue_size(16384) // 8x default, enough for 8 shards under load
.with_max_export_batch_size(2048) // Larger batches for efficiency
.with_scheduled_delay(std::time::Duration::from_millis(100)) // Fast export to prevent queue buildup
.build();
let batch_processor = BatchSpanProcessor::new(exporter, batch_config);
let tracer_provider = SdkTracerProvider::builder()
.with_resource(resource)
.with_span_processor(batch_processor)
.with_sampler(opentelemetry_sdk::trace::Sampler::AlwaysOn)
.build();
View on GitHub (pinned to 6c226ddcb3)
Solutions
- Fix LINERA_OTLP_EXPORTER_ENDPOINT to a fully-qualified tonic-compatible URL with an explicit port, e.g. http://localhost:4317
- Unset LINERA_OTLP_EXPORTER_ENDPOINT (or pass None to init) so tracing falls back to the non-OTLP initializer instead of panicking
- Inspect the exact value with `printf '%s' "$LINERA_OTLP_EXPORTER_ENDPOINT" | od -c` to spot hidden whitespace/newlines, then re-export it cleanly
- If the URL looks valid, check the opentelemetry-otlp crate version and its tonic feature flags: some versions reject endpoints without an explicit port or with non-http schemes
Example fix
// before export LINERA_OTLP_EXPORTER_ENDPOINT=localhost:4317 // no scheme -> exporter build fails, init panics // after export LINERA_OTLP_EXPORTER_ENDPOINT=http://localhost:4317 // or disable OTLP entirely: unset LINERA_OTLP_EXPORTER_ENDPOINT
Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate the endpoint before enabling OTLP
fn valid_otlp_endpoint(s: &str) -> bool {
let t = s.trim();
(t.starts_with("http://") || t.starts_with("https://")) && !t.chars().any(char::is_whitespace)
}
let endpoint = std::env::var("LINERA_OTLP_EXPORTER_ENDPOINT").ok();
let endpoint = endpoint.filter(|ep| !ep.is_empty() && valid_otlp_endpoint(ep));
tracing_init(log_name, endpoint.as_deref()); // None -> OTLP skipped, no panic Prevention
- Always configure LINERA_OTLP_EXPORTER_ENDPOINT as a full http:// or https:// URL with an explicit port
- In CI, inspect env vars once with od -c / cat -A to catch trailing newlines injected by secrets
- Leave the endpoint unset in environments without a collector — the exporter is then never built
When it happens
Trigger: Calling `tracing::init(log_name, Some(ep))` with a non-empty endpoint, or starting a linera-service binary with LINERA_OTLP_EXPORTER_ENDPOINT set to a value the tonic exporter rejects: missing scheme (`localhost:4317` instead of `http://localhost:4317`), an unsupported protocol, stray whitespace/trailing newline/quotes, or an endpoint rejected by the opentelemetry-otlp version in use.
Common situations: Copying a collector address from OTLP docs (bare host:port or `grpc://...`) into LINERA_OTLP_EXPORTER_ENDPOINT; CI secrets that append a trailing newline; upgrading opentelemetry-otlp so endpoint parsing becomes stricter; enabling the variable in an environment where it used to be unset.
Related errors
- test-log: RUST_LOG_SPAN_EVENTS must be valid UTF-8
- owner should be different from spender
- invalid block export configuration: {message}
- Expected an `ExecutionError`. Got: {self:#?}
- Expected an `ExecutionError`. Got: {chain_error:#?}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/5bcfa1a198cd820a.
Report an issue: GitHub.