mastra-ai/mastra · error · Error

Span ${span.spanId} references non-existent parent ${span.pa

Error message

Span ${span.spanId} references non-existent parent ${span.parentSpanId}

What it means

validateTrace rejects traces where a span's parentSpanId points to a spanId not present in the trace. The parent-child span tree would be broken, so the throw prevents incorrect scorer input extraction from an inconsistent hierarchy.

Source

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

 */
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}`);
    }
  }
}

/**
 * Find the most recent model span that contains conversation history
 */
function findPrimaryLLMSpan(spanTree: SpanTree, rootAgentSpan: SpanRecord): SpanRecord {
  const directLLMSpans = getChildrenOfType<SpanRecord>(spanTree, rootAgentSpan.spanId, SpanType.MODEL_GENERATION);
  if (directLLMSpans.length > 0) {
    // There should only be one model generation span per agent run which is a direct child of the root agent span
    return directLLMSpans[0]!;
  }

  throw new Error('No model generation span found in trace');
}

/**

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Persist/retain complete span sets so parents and children are always ingested together
  2. Fix instrumentation so child spans reference parents within the same trace
  3. Orphan-check/repair the trace (attach orphan spans to root or drop them) before scoring

Example fix

// before
spans = allSpans; // some parents missing
// after
const ids = new Set(allSpans.map(s => s.spanId));
spans = allSpans.filter(s => !s.parentSpanId || ids.has(s.parentSpanId));
Defensive patterns

Strategy: validation

Validate before calling

const ids = new Set(trace.spans.map(s => s.spanId));
const orphans = trace.spans.filter(s => s.parentSpanId && !ids.has(s.parentSpanId));
if (orphans.length) throw new Error(`Orphan spans: ${orphans.map(s => s.spanId).join(',')}`);

Type guard

function hasConsistentParents(t: TraceRecord): boolean {
  const ids = new Set(t.spans.map(s => s.spanId));
  return t.spans.every(s => !s.parentSpanId || ids.has(s.parentSpanId));
}

Try / catch

try {
  transformTraceToScorerInputAndOutput(trace);
} catch (e) {
  if (e instanceof Error && /references non-existent parent/.test(e.message)) {
    logger.warn('Trace has orphan spans; repairing before scoring');
  } else throw e;
}

Prevention

When it happens

Trigger: A span in trace.spans has a non-null parentSpanId that no other span in the array contains — e.g. partial span ingestion (parent dropped by retention/sampling), spans imported from another trace, or manually assembled trace data.

Common situations: Retention or sampling policies dropping some spans while keeping children; custom instrumentation creating spans with mismatched parent IDs; cross-trace span copying during debugging tooling.

Related errors


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