mastra-ai/mastra · error · MastraError

OBSERVABILITY_STORAGE_GET_SPANS_NOT_IMPLEMENTED

OBSERVABILITY_STORAGE_GET_SPANS_NOT_IMPLEMENTED

Error message

This storage provider does not support batch-fetching spans

What it means

getSpans() batch-fetches spans by spanId within a single trace; it powers the optimized getBranch() path. The base class default throws, so hitting this error means the storage adapter lacks the batch span-fetch capability needed for branch expansion.

Source

Thrown at packages/core/src/storage/domains/observability/base.ts:310

      if (!isFallbackTrigger) throw error;
    }

    // Fallback: pull the whole trace, walk in memory.
    const trace = await this.getTrace({ traceId: parsed.traceId });
    if (!trace) return null;
    const spans = extractBranchSpans(trace.spans, parsed.spanId, parsed.depth);
    if (spans.length === 0) return null;
    return { traceId: parsed.traceId, spans };
  }

  /**
   * Batch-fetches spans by spanId within a single trace. Used by the
   * optimized {@link getBranch} path to fetch only the spans that belong to
   * the requested branch (after walking the lightweight structure to identify
   * them) instead of pulling the entire trace.
   */
  async getSpans(_args: GetSpansArgs): Promise<GetSpansResponse> {
    throw new MastraError({
      id: 'OBSERVABILITY_STORAGE_GET_SPANS_NOT_IMPLEMENTED',
      domain: ErrorDomain.MASTRA_OBSERVABILITY,
      category: ErrorCategory.SYSTEM,
      text: 'This storage provider does not support batch-fetching spans',
    });
  }

  /**
   * Retrieves a list of traces with optional filtering.
   */
  async listTraces(_args: ListTracesArgs): Promise<ListTracesResponse> {
    throw new MastraError({
      id: 'OBSERVABILITY_STORAGE_LIST_TRACES_NOT_IMPLEMENTED',
      domain: ErrorDomain.MASTRA_OBSERVABILITY,
      category: ErrorCategory.SYSTEM,
      text: 'This storage provider does not support listing traces',
    });
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Override getSpans() in your adapter (SELECT ... WHERE traceId = ? AND spanId IN (...)).
  2. Use getTrace() to fetch all spans of the trace and filter by the requested span ids client-side.
  3. Avoid the getBranch fast path by relying on adapters that implement the full read domain.
  4. Capability-check getSpans before invoking getBranch and choose the full-trace fallback.

Example fix

// before
const spans = await observability.getSpans({ traceId, spanIds });

// after (fallback)
const trace = await observability.getTrace({ traceId });
const spans = trace?.spans.filter(s => spanIds.includes(s.spanId)) ?? [];
Defensive patterns

Strategy: fallback

Validate before calling

const supportsGetSpans = obs.getSpans !== ObservabilityStorage.prototype.getSpans;

Type guard

function supportsBatchSpanFetch(o: { getSpans: unknown }): boolean {
  return o.getSpans !== (ObservabilityStorage.prototype as any).getSpans;
}

Try / catch

try {
  return await obs.getSpans({ traceId, spanIds });
} catch (e) {
  if ((e as MastraError).id === 'OBSERVABILITY_STORAGE_GET_SPANS_NOT_IMPLEMENTED') {
    const trace = await obs.getTrace({ traceId }).catch(() => null);
    return trace?.spans.filter(s => spanIds.includes(s.spanId)) ?? [];
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getSpans({ traceId, spanIds }) directly, or calling getBranch() on an adapter that resolves branches via the lightweight structure + getSpans fast path but did not override getSpans.

Common situations: Custom adapters implementing getStructure but not the batched fetch (getBranch then falls through); minimal storage backends in tests; adapters predating the optimized getBranch implementation.

Related errors


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