googleapis/mcp-toolbox · error

unable to create metric

Error message

unable to create %s metric: %w

What it means

OpenTelemetry meter creation failed for the 'mcp.op.duration' histogram. CreateTelemetryInstrumentation registers several metrics; if the OTel meter API cannot instantiate this Float64Histogram (invalid instrument config or a meter provider in a failed state), it returns this wrapped error and the whole instrumentation setup fails.

Solutions

  1. Ensure otel setup (SetupOTel) runs before CreateTelemetryInstrumentation and Shutdown has not been called first.
  2. Check the wrapped error; if it says the instrument is invalid, verify the metric name and unit are valid in your OTel SDK version.
  3. Avoid double-initializing telemetry; guard Setup with sync.Once or a flag.
  4. Pin compatible versions of go.opentelemetry.io/otel and the metrics SDK in go.mod.
  5. If telemetry is optional, log the error and continue with a no-op instrumentation instead of failing startup.
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure telemetry is initialized before instruments are created
if (!otelReady) { await setupOTel(); } // meter provider must be live

Try / catch

try {
  const instr = createTelemetryInstrumentation();
} catch (e) {
  if (String(e.message).includes("unable to create") && String(e.message).includes("metric")) {
    // log and fall back to no-op instrumentation
  }
}

Prevention

When it happens

Trigger: Calling Setup/CreateTelemetryInstrumentation where meter.Float64Histogram for the MCP operation duration name returns an error — most commonly when the backing OTel SDK meter provider was not initialized or was already shut down.

Common situations: Telemetry set up twice or after Shutdown was called, an OTel SDK version mismatch producing an invalid instrument configuration, or a custom MeterProvider failing to create instruments.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/6c97f8000c91ef7d. Report an issue: GitHub.

Appendix: source

Thrown at internal/telemetry/instrumentation.go:60

	McpActiveSessions     metric.Int64UpDownCounter
	ToolExecutionDuration metric.Float64Histogram
}

func CreateTelemetryInstrumentation(versionString string) (*Instrumentation, error) {
	tracer := otel.Tracer(
		TracerName,
		trace.WithInstrumentationVersion(versionString),
	)

	meter := otel.Meter(MetricName, metric.WithInstrumentationVersion(versionString))

	mcpOperationDuration, err := meter.Float64Histogram(
		mcpOperationDurationName,
		metric.WithDescription("Duration of a single MCP JSON-RPC operation."),
		metric.WithUnit("s"),
	)
	if err != nil {
		return nil, fmt.Errorf("unable to create %s metric: %w", mcpOperationDurationName, err)
	}

	mcpSessionDuration, err := meter.Float64Histogram(
		mcpSessionDurationName,
		metric.WithDescription("Duration of an MCP session."),
		metric.WithUnit("s"),
	)
	if err != nil {
		return nil, fmt.Errorf("unable to create %s metric: %w", mcpSessionDurationName, err)
	}

	mcpActiveSessions, err := meter.Int64UpDownCounter(
		mcpActiveSessionsName,
		metric.WithDescription("Current count of active MCP sessions."),
		metric.WithUnit("{session}"),
	)
	if err != nil {
		return nil, fmt.Errorf("unable to create %s metric: %w", mcpActiveSessionsName, err)

View on GitHub (pinned to 8cc6e09de2)