mastra-ai/mastra · error · MastraError

OBSERVABILITY_TRACE_ID_REQUIRED

OBSERVABILITY_TRACE_ID_REQUIRED

Error message

Trace ID is required for creating a span

What it means

validateCreateSpan also requires traceId: a span must belong to a trace so the store can upsert it into the trace entry. createSpan and batchCreateSpans throw this SYSTEM-category error when record.traceId is falsy.

Source

Thrown at packages/core/src/storage/domains/observability/inmemory.ts:477

        createdAt: now,
        updatedAt: now,
      };
      this.upsertSpanToTrace(record);
    }
  }

  private validateCreateSpan(record: CreateSpanRecord): void {
    if (!record.spanId) {
      throw new MastraError({
        id: 'OBSERVABILITY_SPAN_ID_REQUIRED',
        domain: ErrorDomain.MASTRA_OBSERVABILITY,
        category: ErrorCategory.SYSTEM,
        text: 'Span ID is required for creating a span',
      });
    }

    if (!record.traceId) {
      throw new MastraError({
        id: 'OBSERVABILITY_TRACE_ID_REQUIRED',
        domain: ErrorDomain.MASTRA_OBSERVABILITY,
        category: ErrorCategory.SYSTEM,
        text: 'Trace ID is required for creating a span',
      });
    }
  }

  /**
   * Inserts or updates a span in the trace and recomputes trace-level properties
   */
  private upsertSpanToTrace(span: SpanRecord): void {
    const { traceId, spanId } = span;
    let traceEntry = this.db.traces.get(traceId);

    if (!traceEntry) {
      traceEntry = {
        spans: {},

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Create spans within an active trace or explicitly set traceId (use the trace's id, or create the trace first via createTrace).
  2. Propagate trace context through async boundaries (AsyncLocalStorage / context carriers) so spans inherit traceId.
  3. Fix field mapping when importing spans from other tracers so traceId is preserved.
  4. Validate span records for both traceId and spanId before batch submission.

Example fix

// before
await storage.createSpan({ spanId, name: 'tool-call' }); // throws

// after
await storage.createSpan({ traceId: activeTrace.id, spanId, name: 'tool-call' });
Defensive patterns

Strategy: validation

Validate before calling

if (!activeTrace?.id) throw new Error('Cannot create span outside a trace');
await storage.createSpan({ traceId: activeTrace.id, spanId, ... });

Type guard

function isSpanInTrace(r: CreateSpanRecord): r is CreateSpanRecord & { traceId: string } {
  return typeof r.traceId === 'string' && r.traceId.length > 0;
}

Try / catch

try {
  await storage.createSpan(record);
} catch (e) {
  if ((e as MastraError).id === 'OBSERVABILITY_TRACE_ID_REQUIRED') {
    logger.error('Span dropped: no trace context', record);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createSpan or batchCreateSpans with a record missing traceId — e.g. creating a root span without establishing/propagating its trace context.

Common situations: Starting spans outside a trace context (no active trace); losing traceId when spans cross async boundaries or serialization; a tracer integration not propagating trace context; manual span construction in tests.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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