denoland/deno · error
Env var OTEL_EXPORTER_OTLP_PROTOCOL specifies an unsupported
Error message
Env var OTEL_EXPORTER_OTLP_PROTOCOL specifies an unsupported protocol: {} What it means
OTEL_EXPORTER_OTLP_PROTOCOL picks the wire format for the OTLP exporter. Supported values are `console`, `http/protobuf` (also the default when the variable is unset or empty), `http/json` and `grpc`. Any other value aborts telemetry initialization.
Source
Thrown at ext/telemetry/lib.rs:1254
// Parse the `OTEL_EXPORTER_OTLP_PROTOCOL` variable. The opentelemetry_*
// crates don't do this automatically.
// `opentelemetry_otlp::Protocol::Grpc` is feature-gated behind the
// (tonic-based) `grpc-tonic` feature, which we don't enable because we ship
// our own gRPC framing. Track the gRPC choice with a separate flag so the
// `protocol` value is only ever the HTTP variant passed to the OTLP HTTP
// exporter builder.
let protocol_var = sys.env_var("OTEL_EXPORTER_OTLP_PROTOCOL");
let (use_console_exporter, use_grpc, protocol) = match protocol_var.as_deref()
{
Ok("console") => (true, false, Protocol::HttpBinary),
Ok("http/protobuf") | Ok("") | Err(std::env::VarError::NotPresent) => {
(false, false, Protocol::HttpBinary)
}
Ok("http/json") => (false, false, Protocol::HttpJson),
Ok("grpc") => (false, true, Protocol::HttpBinary),
Ok(protocol) => {
return Err(deno_core::anyhow::anyhow!(
"Env var OTEL_EXPORTER_OTLP_PROTOCOL specifies an unsupported protocol: {}",
protocol
));
}
Err(err) => {
return Err(deno_core::anyhow::anyhow!(
"Failed to read env var OTEL_EXPORTER_OTLP_PROTOCOL: {}",
err
));
}
};
// Define the resource attributes that will be attached to all log records.
// These attributes are sourced as follows (in order of precedence):
// * The `service.name` attribute from the `OTEL_SERVICE_NAME` env var.
// * Additional attributes from the `OTEL_RESOURCE_ATTRIBUTES` env var.
// * Default attribute values defined here.
// TODO(piscisaureus): add more default attributes (e.g. script path).View on GitHub (pinned to 89f33cbef2)
Solutions
- Set the variable to one of `console`, `http/protobuf`, `http/json`, `grpc`
- Unset it to use the default `http/protobuf`
- Put the collector address in OTEL_EXPORTER_OTLP_ENDPOINT, never in the protocol variable
Example fix
# before — endpoint URL or bare format name export OTEL_EXPORTER_OTLP_PROTOCOL=http://localhost:4317 # after — exact protocol name; endpoint goes in its own variable export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
Defensive patterns
Strategy: validation
Validate before calling
case "${OTEL_EXPORTER_OTLP_PROTOCOL:-}" in
""|console|http/protobuf|http/json|grpc) ;;
*) echo "unsupported OTEL_EXPORTER_OTLP_PROTOCOL: '$OTEL_EXPORTER_OTLP_PROTOCOL'"; exit 1;;
esac
deno run --unstable-otel main.ts Type guard
const PROTOCOLS = new Set(["console", "http/protobuf", "http/json", "grpc"]); const isOtlpProtocol = (v: string): boolean => v === "" || PROTOCOLS.has(v);
Prevention
- Protocol names contain a literal slash: http/protobuf and http/json
- The collector address belongs in OTEL_EXPORTER_OTLP_ENDPOINT
- Leave the variable unset for the default http/protobuf
When it happens
Trigger: Setting the variable to an unsupported string: `protobuf`, `grpc/protobuf`, URL-escaped variants like `http%2Fprotobuf`, or a full URL such as `http://localhost:4317`.
Common situations: Confusing the protocol name with the endpoint URL; env values mangled by escaping when copied between systems; typos in Helm charts or docker-compose env blocks.
Related errors
- vsock is not supported on this platform
- invalid vsock addr
- no private key found in OTEL_EXPORTER_OTLP_CLIENT_KEY file
- Env var OTEL_TRACES_SAMPLER specifies an unsupported sampler
- Failed to read env var OTEL_EXPORTER_OTLP_PROTOCOL: {}
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/7864c0c7cd1e7610.
Report an issue: GitHub.