mastra-ai/mastra · error · MastraError
OBSERVABILITY_SPAN_ID_REQUIRED
OBSERVABILITY_SPAN_ID_REQUIRED
Error message
Span ID is required for creating a span
What it means
validateCreateSpan enforces that every span record persisted to the in-memory observability store carries a spanId; spans without one cannot be keyed inside their trace. createSpan and batchCreateSpans throw this SYSTEM-category error when record.spanId is falsy.
Source
Thrown at packages/core/src/storage/domains/observability/inmemory.ts:468
this.upsertSpanToTrace(record);
}
async batchCreateSpans(args: BatchCreateSpansArgs): Promise<void> {
const now = new Date();
for (const span of args.records) {
this.validateCreateSpan(span);
const record: SpanRecord = {
...span,
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',
});
}
}
/**View on GitHub (pinned to 75dd419e61)
Solutions
- Populate spanId on every span before calling createSpan/batchCreateSpans (e.g. crypto.randomUUID()).
- When importing from another tracing system, map its span-id field to spanId explicitly.
- Filter or fix records missing spanId before batch submission instead of letting one bad record abort the batch.
- Verify the span object is not being spread from a source that omits/span-renames the id.
Example fix
// before
await storage.createSpan({ traceId, name: 'llm-call' }); // throws
// after
await storage.createSpan({ traceId, spanId: crypto.randomUUID(), name: 'llm-call' }); Defensive patterns
Strategy: validation
Validate before calling
function assertSpanRecord(r: CreateSpanRecord): void {
if (!r.spanId) throw new Error('spanId is required');
if (!r.traceId) throw new Error('traceId is required');
}
spans.forEach(assertSpanRecord);
await storage.batchCreateSpans(spans); Type guard
function isCreateableSpan(r: CreateSpanRecord): r is CreateSpanRecord & { spanId: string; traceId: string } {
return Boolean(r.spanId) && Boolean(r.traceId);
} Try / catch
try {
await storage.createSpan(record);
} catch (e) {
if ((e as MastraError).id === 'OBSERVABILITY_SPAN_ID_REQUIRED') {
logger.error('Span dropped: missing spanId', record);
} else throw e;
} Prevention
- Generate spanId at span creation time, before any async work.
- Map external tracer id fields (e.g. OTel spanContext().spanId) to spanId explicitly.
- Filter invalid records out of batches before submission.
- Type spans with a branded required-id type in your tracer wrapper.
When it happens
Trigger: Calling createSpan or batchCreateSpans with a CreateSpanRecord lacking spanId (undefined, null, or empty string).
Common situations: Mapping external tracing data (OTel, custom tracers) where the span id field has a different name; dropping fields during serialization; constructing spans manually in tests; a tracer bug emitting spans before assigning ids.
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
- OBSERVABILITY_TRACE_ID_REQUIRED
- Trace not found for scoring, traceId: ${target.traceId}
- OBSERVABILITY_CREATE_SPAN_NOT_IMPLEMENTED
- OBSERVABILITY_STORAGE_UPDATE_SPAN_NOT_IMPLEMENTED
- OBSERVABILITY_STORAGE_GET_SPAN_NOT_IMPLEMENTED
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/566d3e717d38238a.
Report an issue: GitHub.