mastra-ai/mastra · critical

SpanConverter not initialized correctly

Error message

SpanConverter not initialized correctly

What it means

SpanConverter lazily initializes its OpenTelemetry Resource and scope (instrumentation scope) on first use via initIfNeeded(), then converts Mastra exported spans into OTLP ReadableSpans. If resource or scope is still undefined after initIfNeeded, its internal state is inconsistent and it throws rather than emitting malformed telemetry. This indicates an SDK/tracer-provider setup problem, not bad span data.

Source

Thrown at observability/otel-exporter/src/span-converter.ts:97

      this.resource = resource;
      this.scope = {
        name: this.params.packageName,
        version: packageVersion,
      };
    })();

    return this.initPromise;
  }

  /**
   * Convert a Mastra Span to an OpenTelemetry ReadableSpan
   */
  async convertSpan(span: AnyExportedSpan): Promise<ReadableSpan> {
    await this.initIfNeeded();

    if (!this.resource || !this.scope) {
      throw new Error('SpanConverter not initialized correctly');
    }

    // --- Core fields derived from Mastra span ---
    const name = getSpanName(span);
    const kind = getSpanKind(span.type);
    const attributes = getAttributes(span);

    // Add metadata as custom attributes (not gen_ai specific)
    if (span.metadata) {
      for (const [k, v] of Object.entries(span.metadata)) {
        if (v === null || v === undefined) {
          continue;
        }
        attributes[`mastra.metadata.${k}`] = typeof v === 'object' ? JSON.stringify(v) : v;
      }
    }

    // Add tags for root spans (only root spans can have tags)

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the OTEL exporter (and its tracer provider) is fully configured in Mastra observability options before spans are exported.
  2. If using SpanConverter directly, call await converter.initIfNeeded() yourself and verify resource/scope are set before converting.
  3. Check that @opentelemetry/sdk-trace-base/NodeSDK is initialized in the process (or a valid Resource is provided); missing SDK init is the usual cause.
  4. Upgrade @mastra/observability + otel-exporter packages together to fix known init-race bugs.

Example fix

// before: converting before provider init
const converter = new SpanConverter();
const rs = await converter.convertSpan(span);
// after: explicit init and guard
const converter = new SpanConverter();
await converter.initIfNeeded();
if (!isSpanConverterReady(converter)) throw new Error('Initialize OTel SDK before exporting spans');
const rs = await converter.convertSpan(span);
Defensive patterns

Strategy: type-guard

Validate before calling

import { trace } from '@opentelemetry/api';
if (!trace.getTracerProvider()) {
  throw new Error('OpenTelemetry SDK not initialized; set up NodeSDK before exporting Mastra spans');
}

Type guard

function isSpanConverterReady(c: object): boolean {
  return 'resource' in c && 'scope' in c && !!(c as any).resource && !!(c as any).scope;
}

Try / catch

try {
  const readable = await converter.convertSpan(span);
} catch (err) {
  if (String(err.message) === 'SpanConverter not initialized correctly') {
    console.error('OTel provider/resource missing; initialize the observability exporter before spans flush');
    return; // or re-export after init
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling convertSpan (directly or via otelSpan/readableSpan/result/llmResult/toolResult/rootResult helpers) when SpanConverter.initIfNeeded failed to set this.resource/this.scope — e.g. no OpenTelemetry tracer provider/SDK registered, init awaited a promise that resolved without setup, or the converter was constructed in an environment where OTel resource detection returned nothing.

Common situations: Exporting spans in serverless/edge runtimes without @opentelemetry/sdk-trace-base initialized; forgetting to configure the observability OTEL provider before spans flush; custom exporter instantiating SpanConverter directly instead of through the configured exporter; race where export runs before init completes.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/0104f3d9bc271a61. Report an issue: GitHub.