mastra-ai/mastra · error
Structure mismatch in snapshot: Expected: ${expectedStructu
Error message
Structure mismatch in snapshot:
Expected:
${expectedStructure.join('
')}
Actual:
${structureGraph.join('
')}
Differences:
${structureMismatches.join('
')}
Snapshot: ${snapshotPath}
Run with { updateSnapshot: true } to update. What it means
TestExporter's assertMatchesSnapshot first compares a lightweight ASCII 'structure graph' of the recorded span tree (span names/types/nesting) against the __structure__ section of the snapshot file. If any line differs, it means the shape of the traced spans changed relative to the stored snapshot, and it throws before doing the deeper field-by-field comparison. This is an intentional assertion failure, not a runtime fault.
Source
Thrown at observability/mastra/src/exporters/test.ts:1327
if (Array.isArray(snapshotData)) {
// Old format: just the spans array
expectedSpans = snapshotData;
} else if (snapshotData && typeof snapshotData === 'object' && 'spans' in snapshotData) {
// New format: { __structure__, spans }
expectedSpans = snapshotData.spans;
expectedStructure = snapshotData.__structure__;
} else {
throw new Error(
`Invalid snapshot format in ${snapshotPath}.\n` + `Expected an array or object with 'spans' property.`,
);
}
// Compare structure first (quick validation)
if (expectedStructure) {
const structureMismatches = this.#compareStructure(structureGraph, expectedStructure);
if (structureMismatches.length > 0) {
throw new Error(
`Structure mismatch in snapshot:\n\n` +
`Expected:\n${expectedStructure.join('\n')}\n\n` +
`Actual:\n${structureGraph.join('\n')}\n\n` +
`Differences:\n${structureMismatches.join('\n')}\n\n` +
`Snapshot: ${snapshotPath}\n` +
`Run with { updateSnapshot: true } to update.`,
);
}
}
// Deep compare spans
const mismatches: { path: string; expected: unknown; actual: unknown }[] = [];
this.#deepCompareWithMarkers(normalizedTree, expectedSpans, '$.spans', mismatches);
if (mismatches.length > 0) {
const mismatchDetails = mismatches
.map(
(m, i) =>View on GitHub (pinned to 75dd419e61)
Solutions
- If the new structure is correct, re-record with exporter.assertMatchesSnapshot(name, { updateSnapshot: true }).
- Diff the 'Expected' vs 'Actual' trees in the message to find which span appears, disappears, or moved, and fix the test or traced code accordingly.
- If the change came from a Mastra upgrade, regenerate all tracing snapshots as part of the upgrade and commit them.
- Make the traced operation deterministic (fixed model output, fixed tool results) so the span tree is stable across runs.
Example fix
// before
await exporter.assertMatchesSnapshot('agent-trace.snap');
// after (intentional structural change)
await exporter.assertMatchesSnapshot('agent-trace.snap', { updateSnapshot: true }); Defensive patterns
Strategy: try-catch
Validate before calling
const snap = JSON.parse(fs.readFileSync(path.join('__snapshots__', name), 'utf-8'));
if (!snap || !Array.isArray(snap.__structure__)) throw new Error('Snapshot missing __structure__; re-record it'); Type guard
function hasStructure(s: unknown): s is { __structure__: string[]; spans: unknown } {
return typeof s === 'object' && s !== null && 'spans' in s && Array.isArray((s as any).__structure__);
} Try / catch
try {
await exporter.assertMatchesSnapshot('agent-trace.snap');
} catch (err) {
if (String(err.message).startsWith('Structure mismatch in snapshot')) {
// print diff, optionally auto-update in a local flag mode
if (process.env.UPDATE_SNAPSHOTS) return exporter.assertMatchesSnapshot('agent-trace.snap', { updateSnapshot: true });
}
throw err;
} Prevention
- Regenerate snapshots whenever you upgrade @mastra/observability.
- Keep traced test operations deterministic (mock model/tool output).
- Review __structure__ diffs in CI before blanket-updating snapshots.
- Treat updateSnapshot runs as reviewed changes, not test fixes.
When it happens
Trigger: Calling exporter.assertMatchesSnapshot(name) when the generated structureGraph differs from snapshotData.__structure__ — e.g. the AI operation created different spans, a new/removed nesting level, renamed span types, or the snapshot was generated by an older @mastra/observability version.
Common situations: Upgrading Mastra and running stale snapshots; adding/removing a tool call, workflow step, or LLM call that changes span nesting; non-deterministic agent behavior producing different child spans; hand-editing a snapshot and breaking the __structure__ block.
Related errors
- Snapshot has ${mismatches.length} mismatch${mismatches.lengt
- OBSERVABILITY_STORAGE_BATCH_UPDATE_SPANS_NOT_IMPLEMENTED
- Span not found
- OBSERVABILITY_INVALID_CONFIG
- OBSERVABILITY_INVALID_INSTANCE_CONFIG
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/51a33ce79898c8d0.
Report an issue: GitHub.