mastra-ai/mastra · critical · Error

TokenCostControl requires observability storage with getMetr

Error message

TokenCostControl requires observability storage with getMetricAggregate support. Configure observability storage on your Mastra instance.

What it means

TokenCostControl queries historical usage via the observability store's `getMetricAggregate`. In `__registerMastra` (called when the processor is attached to a Mastra instance), it checks that storage exists and exposes that method; if not, it throws, because without observability storage it cannot aggregate token/cost metrics. Note the check is for `getMetricAggregate` support — older storage adapters lack it.

Source

Thrown at packages/core/src/processors/processors/token-cost-control.ts:283

      if (!Number.isFinite(options.warnAtPercent) || options.warnAtPercent <= 0 || options.warnAtPercent >= 100) {
        throw new Error('TokenCostControl requires warnAtPercent to be a number between 0 and 100 (exclusive)');
      }
      this.warnAtPercent = options.warnAtPercent;
    }

    this.maxCost = options.maxCost;
    this.scope = options.scope ?? 'resource';
    this.window = options.window ?? '7d';
    this.strategy = options.strategy ?? 'block';
    this.messageTemplate = options.message ?? 'Cost control: estimated cost limit exceeded ({usage}/{limit})';
    this.includeBreakdown = options.includeBreakdown ?? false;
  }

  __registerMastra(mastra: Mastra<any, any, any, any, any, any, any, any, any, any>): void {
    const storage = mastra.getStorage();
    const obsStorage = storage?.stores?.observability;
    if (!obsStorage || typeof obsStorage.getMetricAggregate !== 'function') {
      throw new Error(
        `TokenCostControl requires observability storage with getMetricAggregate support. ` +
          'Configure observability storage on your Mastra instance.',
      );
    }
    this.observabilityStorage = obsStorage;
    this.logger = mastra.getLogger();
  }

  private resolveScopeFilter(
    requestContext?: RequestContext,
    traceId?: string,
  ): { filter: Record<string, string>; scopeKey?: string } | undefined {
    if (this.scope === 'run') {
      if (!traceId) return undefined;
      return { filter: { traceId } };
    }

    // Reserved keys from RequestContext take precedence (set by auth middleware).

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Configure storage with an observability store on your Mastra instance: `new Mastra({ storage: new LibSQLStore(...), observability: {...} })` (per current docs).
  2. Upgrade @mastra/core and your storage package to versions where the observability store implements `getMetricAggregate`.
  3. Verify with `mastra.getStorage()?.stores?.observability?.getMetricAggregate` before registering the processor.
  4. In tests/minimal setups, swap TokenCostControl for a processor that doesn't need metric aggregation.

Example fix

// before
new Mastra({ agents }); // no storage
// after
new Mastra({ agents, storage: new LibSQLStore({ url: process.env.DB_URL }), observability: { default: { enabled: true } } });
Defensive patterns

Strategy: validation

Validate before calling

const obs = mastra.getStorage()?.stores?.observability;
if (!obs || typeof obs.getMetricAggregate !== 'function') {
  throw new Error('TokenCostControl requires observability storage with getMetricAggregate support');
}

Type guard

function supportsMetricAggregate(s: unknown): s is { getMetricAggregate: (...args: unknown[]) => Promise<unknown> } {
  return typeof (s as any)?.getMetricAggregate === 'function';
}

Try / catch

try {
  mastra.register(processor); // triggers __registerMastra
} catch (e) {
  if (e.message.includes('observability storage')) {
    console.error('Enable observability storage on Mastra before using TokenCostControl');
    processors = processors.filter(p => p !== processor);
  } else throw e;
}

Prevention

When it happens

Trigger: Registering TokenCostControl on a Mastra instance created without storage (`new Mastra({ ... })` with no `storage`), with a storage backend whose observability store doesn't implement `getMetricAggregate` (outdated @mastra/core storage adapters or third-party stores), or `mastra.getStorage()` returning undefined.

Common situations: Deployments where storage was configured for workflows/threads but not observability, upgrading core without upgrading storage packages (version mismatch), in-memory setups that never configured observability storage, and tests using minimal Mastra instances.

Related errors


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