mastra-ai/mastra · error

shareTokenBudget requires async buffering to be disabled (th

Error message

shareTokenBudget requires async buffering to be disabled (this is a temporary limitation). Add observation: { bufferTokens: false } to your config:

  observationalMemory: {
    shareTokenBudget: true,
    observation: { bufferTokens: false },
  }

Async buffering is enabled by default — this opt-out is only needed when using shareTokenBudget.

What it means

Same shareTokenBudget vs async-buffering restriction, but for the default case: async buffering is enabled by default, so merely setting shareTokenBudget: true without opting out throws. The message explains that the bufferTokens: false opt-out is only needed when using shareTokenBudget.

Source

Thrown at packages/memory/src/processors/observational-memory/observational-memory.ts:563

    const asyncBufferingDisabled =
      config.observation?.bufferTokens === false || (config.scope === 'resource' && !userExplicitlyConfiguredAsync);

    // shareTokenBudget is not yet compatible with async buffering (temporary limitation).
    // To use shareTokenBudget, users must explicitly disable buffering.
    if (isSharedBudget && !asyncBufferingDisabled) {
      const common =
        `shareTokenBudget requires async buffering to be disabled (this is a temporary limitation). ` +
        `Add observation: { bufferTokens: false } to your config:\n\n` +
        `  observationalMemory: {\n` +
        `    shareTokenBudget: true,\n` +
        `    observation: { bufferTokens: false },\n` +
        `  }\n`;
      if (userExplicitlyConfiguredAsync) {
        throw new Error(
          common + `\nRemove any other async buffering settings (bufferTokens, bufferActivation, blockAfter).`,
        );
      } else {
        throw new Error(
          common + `\nAsync buffering is enabled by default — this opt-out is only needed when using shareTokenBudget.`,
        );
      }
    }

    const observationActivateAfterIdle = config.observation?.activateAfterIdle ?? config.activateAfterIdle;
    const observationActivateAfterIdlePath =
      config.observation?.activateAfterIdle !== undefined ? 'observation.activateAfterIdle' : 'activateAfterIdle';

    // Resolve observation config with defaults
    this.observationConfig = {
      model: observationModel,
      // When shared budget, store as range: min = base threshold, max = total budget
      // This allows messages to expand into unused observation space
      messageTokens: isSharedBudget ? { min: messageTokens, max: totalBudget } : messageTokens,
      shareTokenBudget: isSharedBudget,
      modelSettings: {
        temperature:

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set observation: { bufferTokens: false } alongside shareTokenBudget: true
  2. Remove shareTokenBudget: true if you want to keep default async buffering
  3. Disable async buffering at the config-construction site where shareTokenBudget is toggled, not ad hoc

Example fix

// before
new ObservationalMemory({ model, shareTokenBudget: true })
// after
new ObservationalMemory({
  model,
  shareTokenBudget: true,
  observation: { bufferTokens: false }
})
Defensive patterns

Strategy: validation

Validate before calling

function assertShareTokenBudgetOptOut(c: ObservationalMemoryConfig): void {
  if (c.shareTokenBudget && c.observation?.bufferTokens !== false) {
    throw new Error('shareTokenBudget requires observation: { bufferTokens: false } (async buffering is on by default)');
  }
}

Type guard

function isShareTokenBudgetConfig(c: ObservationalMemoryConfig): boolean {
  return !c.shareTokenBudget || c.observation?.bufferTokens === false;
}

Try / catch

try {
  const mem = new ObservationalMemory(config);
} catch (err) {
  if (err instanceof Error && err.message.includes('shareTokenBudget requires async buffering')) {
    config.observation = { ...config.observation, bufferTokens: false };
  } else throw err;
}

Prevention

When it happens

Trigger: new ObservationalMemory({ shareTokenBudget: true, ... }) with no explicit observation.bufferTokens: false — the implicit default async buffering triggers the error.

Common situations: First-time adoption of shareTokenBudget without reading the buffering caveat; minimal configs copied from older examples that predate the default buffering.

Related errors


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