mastra-ai/mastra · error · Error

Trace is null or undefined

Error message

Trace is null or undefined

What it means

validateTrace in the score-traces utils throws this plain Error when the trace record passed for scorer transformation is null or undefined. It is a precondition check ensuring downstream span-tree building never operates on a missing trace.

Source

Thrown at packages/core/src/evals/scoreTraces/utils.ts:217

function reconstructToolInvocations(spanTree: SpanTree, parentSpanId: string) {
  const toolSpans = getChildrenOfType<SpanRecord>(spanTree, parentSpanId, SpanType.TOOL_CALL);

  return toolSpans.map(toolSpan => ({
    toolCallId: toolSpan.spanId,
    toolName: toolSpan.entityName ?? toolSpan.entityId ?? 'unknown',
    toolId: toolSpan.entityId,
    args: toolSpan.input || {},
    result: toolSpan.output || {},
    state: 'result' as const,
  }));
}

/**
 * Validate trace structure and throw descriptive errors
 */
export function validateTrace(trace: TraceRecord): void {
  if (!trace) {
    throw new Error('Trace is null or undefined');
  }

  if (!trace.spans || !Array.isArray(trace.spans)) {
    throw new Error('Trace must have a spans array');
  }

  if (trace.spans.length === 0) {
    throw new Error('Trace has no spans');
  }

  // Check for circular references in parent-child relationships
  const spanIds = new Set(trace.spans.map(span => span.spanId));
  for (const span of trace.spans) {
    if (span.parentSpanId && !spanIds.has(span.parentSpanId)) {
      throw new Error(`Span ${span.spanId} references non-existent parent ${span.parentSpanId}`);
    }
  }
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check the trace lookup result for null/undefined before invoking the scorer transformation
  2. Verify the traceId exists in the configured storage (query the observability store first)
  3. Ensure the trace has finished and been persisted before triggering the scoring workflow

Example fix

// before
const input = transformTraceToScorerInputAndOutput(trace);
// after
if (!trace) return; // or fetch/await the trace first
const input = transformTraceToScorerInputAndOutput(trace);
Defensive patterns

Strategy: type-guard

Validate before calling

const trace = await storage.getStore('observability')?.getTrace({ traceId });
if (!trace) throw new Error(`Trace ${traceId} not found`);

Type guard

function isTraceRecord(t: TraceRecord | null | undefined): t is TraceRecord {
  return t != null && typeof t === 'object' && Array.isArray((t as TraceRecord).spans);
}

Try / catch

try {
  transformTraceToScorerInputAndOutput(trace);
} catch (e) {
  if (e instanceof Error && e.message === 'Trace is null or undefined') {
    logger.warn('Skipping scoring: trace missing', { traceId });
  } else throw e;
}

Prevention

When it happens

Trigger: prepareTraceForTransformation receiving a null/undefined TraceRecord — e.g. storage.getTrace / trace lookup returned nothing for the requested traceId and the result was passed through unchecked.

Common situations: Scoring a traceId that does not exist (wrong ID, wrong storage backend, data pruned by retention); async trace lookup racing with ingestion so the record is not yet persisted.

Related errors


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