mastra-ai/mastra · warning · HTTPException
Span not found
Error message
Span not found
What it means
The span endpoint resolves a single span via `observabilityStore.getSpan({ traceId, spanId })`; when nothing is returned the handler throws a 404 'Span not found'. Both the trace and the specific span ID must exist in the store.
Source
Thrown at packages/server/src/server/handlers/observability.ts:347
/** Route: GET /observability/traces/:traceId/spans/:spanId - get a single span with full details. */
export const GET_SPAN_ROUTE: ServerRoute = createRoute({
method: 'GET',
path: '/observability/traces/:traceId/spans/:spanId',
responseType: 'json',
pathParamSchema: getSpanArgsSchema,
responseSchema: getSpanResponseSchema,
summary: 'Get a single span by ID',
description: 'Returns a complete span record with all details by trace ID and span ID',
tags: ['Observability'],
requiresAuth: true,
handler: async ({ mastra, traceId, spanId }) => {
try {
const observabilityStore = await getObservabilityStore(mastra);
const span = await observabilityStore.getSpan({ traceId, spanId });
if (!span) {
throw new HTTPException(404, { message: `Span not found` });
}
return span;
} catch (error) {
return handleError(error, 'Error getting span');
}
},
});
/** Route: GET /observability/traces/:traceId/trajectory - extract trajectory from a trace. */
export const GET_TRACE_TRAJECTORY_ROUTE = createRoute({
method: 'GET',
path: '/observability/traces/:traceId/trajectory',
responseType: 'json',
pathParamSchema: getTraceArgsSchema,
responseSchema: z.object({
steps: z.array(z.unknown()),
totalDurationMs: z.number().optional(),View on GitHub (pinned to 75dd419e61)
Solutions
- Fetch the full trace first and pick a spanId from its spans array.
- Confirm the spanId belongs to the given traceId (IDs are not globally unique).
- Check the storage backend for ingestion gaps or write errors.
- Return a graceful 'span unavailable' UI state on 404.
Example fix
// before
const span = await fetch(`/api/observability/traces/${traceId}/spans/${spanId}`).then(r => r.json());
// after
const trace = await fetch(`/api/observability/traces/${traceId}`).then(r => r.json());
const span = trace.spans.find(s => s.id === spanId);
if (!span) throw new Error(`Span ${spanId} not in trace ${traceId}`); Defensive patterns
Strategy: validation
Validate before calling
const trace = await getTrace(traceId);
if (!trace.spans.some(s => s.id === spanId)) {
throw new Error(`Span ${spanId} not in trace ${traceId}`);
} Type guard
function hasSpan(trace: { spans: { id: string }[] }, spanId: string): boolean {
return trace.spans.some(s => s.id === spanId);
} Try / catch
try {
return await getSpan(traceId, spanId);
} catch (e) {
if (is404(e)) return null; // span unavailable
throw e;
} Prevention
- Derive spanIds from the trace response rather than external logs.
- Remember span IDs are scoped per trace, not globally unique.
- Check ingestion health if spans are routinely missing from stored traces.
When it happens
Trigger: Calling GET /api/observability/traces/:traceId/spans/:spanId where the spanId doesn't exist under that trace — wrong span ID, span from a different trace, or partial ingestion (trace exists but span wasn't persisted).
Common situations: Referencing a span ID from logs of a different trace; storage write failures dropped individual spans; querying in-progress traces before the span was flushed.
Related errors
- Trace with ID '${traceId}' not found
- Structure mismatch in snapshot: Expected: ${expectedStructu
- Span not found for scoring, traceId: ${trace.traceId}, spanI
- Trace not found for scoring, traceId: ${target.traceId}
- OBSERVABILITY_CREATE_SPAN_NOT_IMPLEMENTED
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/82101e497748856c.
Report an issue: GitHub.