claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

CLI crashes when `OTEL_*_EXPORTER=none` is set (standard OpenTelemetry SDK value)

Open nsheaps opened this issue 3 weeks ago • 2 comments

human note: the following was written by claude but iterated on to get the full picture with proof from the obfuscated code. It's a real issue, but it's verbose because claude wrote it


The CLI crashes during startup when any of the OTEL exporter environment variables are set to `none`:
  • OTEL_LOGS_EXPORTER=none
  • OTEL_TRACES_EXPORTER=none
  • OTEL_METRICS_EXPORTER=none

Stack Trace

Error: Unknown exporter type set in OTEL_LOGS_EXPORTER env var: none
    at sf7 (/$bunfs/root/claude:2227:1350)
    at EAB (/$bunfs/root/claude:2227:5137)
    at e68 (/$bunfs/root/claude:4669:17047)
    at WPA (/$bunfs/root/claude:4669:17013)
    at JPA (/$bunfs/root/claude:4669:16978)

Expected Behavior

According to the OpenTelemetry SDK Environment Variables specification, none is a valid value for all exporter environment variables:

none: No automatically configured exporter for this signal.

The CLI should recognize none as a valid value and simply skip configuring an exporter for that signal type, rather than throwing an error.

OTEL Spec Compliance Table

Environment Variable OTEL Spec Values CLI Supported Values Missing Values
OTEL_TRACES_EXPORTER otlp, zipkin, console, none otlp, console none, zipkin
OTEL_METRICS_EXPORTER otlp, prometheus, console, none otlp, console, prometheus none
OTEL_LOGS_EXPORTER otlp, console, none otlp, console none

Note: The OTEL spec also defines deprecated values like logging and development values like otlp/stdout, but none is the critical missing value as it's the standard way to disable telemetry.

Why This Matters

Users who have OTEL_*_EXPORTER=none set in their environment (a common way to disable telemetry in OTEL-aware applications) cannot use Claude Code without unsetting those variables first.

This is problematic because:

  • Users may have these set globally via shell profiles
  • It violates the principle of least surprise - these are standard OTEL values

Reproduction

OTEL_LOGS_EXPORTER=none claude -p "say hi"

Code Location

The issue is in the telemetry initialization code (path /$bunfs/root/claude in the Bun-bundled binary, or cli.js in npm package). Three functions handle the exporter environment variables (minified function names vary by version):

Logs Exporter (gm5 in v0.2.6):

function gm5(){let A=(process.env.OTEL_LOGS_EXPORTER||"").trim().split(",").filter(Boolean),Q=[];for(let B of A)if(B==="console")Q.push(new ds.ConsoleLogRecordExporter);else if(B==="otlp"){/* ... */}else throw Error(`Unknown exporter type set in OTEL_LOGS_EXPORTER env var: ${B}`);return Q}

Traces Exporter (um5 in v0.2.6):

function um5(){let A=(process.env.OTEL_TRACES_EXPORTER||"").trim().split(",").filter(Boolean),Q=[];for(let B of A)if(B==="console")Q.push(new ps.ConsoleSpanExporter);else if(B==="otlp"){/* ... */}else throw Error(`Unknown exporter type set in OTEL_TRACES_EXPORTER env var: ${B}`);return Q}

Metrics Exporter (hm5 in v0.2.6):

function hm5(){let A=(process.env.OTEL_METRICS_EXPORTER||"").trim().split(",").filter(Boolean),/* ... */;for(let G of A)if(G==="console"){/* ... */}else if(G==="otlp"){/* ... */}else if(G==="prometheus")B.push(new sv2.PrometheusExporter);else throw Error(`Unknown exporter type set in OTEL_EXPORTER_OTLP_METRICS_PROTOCOL or OTEL_EXPORTER_OTLP_PROTOCOL env var: ${G}`);/* ... */}
Deobfuscated/reformatted version (logs exporter example)
function getLogExporters() {
  let exporterNames = (process.env.OTEL_LOGS_EXPORTER || "").trim().split(",").filter(Boolean);
  let exporters = [];

  for (let name of exporterNames) {
    if (name === "console") {
      exporters.push(new ConsoleLogRecordExporter());
    } else if (name === "otlp") {
      // Configure OTLP exporter based on protocol...
    } else {
      // BUG: "none" falls through to here and throws
      throw Error(`Unknown exporter type set in OTEL_LOGS_EXPORTER env var: ${name}`);
    }
  }
  return exporters;
}

Suggested Fix

Add handling for none in all three exporter configuration functions:

  1. For each of OTEL_LOGS_EXPORTER, OTEL_TRACES_EXPORTER, and OTEL_METRICS_EXPORTER:
    • When iterating through the comma-separated exporter values
    • If the value is "none", skip it (continue to next iteration)
    • Per OTEL spec: none means "no automatically configured exporter for this signal"

This is a simple change: add a condition to check for "none" and continue before the existing console/otlp/prometheus checks and before the error throw.

Current Workaround

Unset the environment variables before running Claude:

unset OTEL_LOGS_EXPORTER OTEL_TRACES_EXPORTER OTEL_METRICS_EXPORTER
claude -p "say hi"

Environment

  • Claude Code Version: 2.1.7
  • OS: macOS

References


🤖 Generated with Claude Code

nsheaps avatar Jan 15 '26 01:01 nsheaps