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 },
  }

Remove any other async buffering settings (bufferTokens, bufferActivation, blockAfter).

What it means

shareTokenBudget is temporarily incompatible with async observation buffering. When the user explicitly configured async buffering options (bufferTokens, bufferActivation, or blockAfter) together with shareTokenBudget, the constructor throws with instructions to disable buffering.

Source

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

    const userExplicitlyConfiguredAsync =
      config.observation?.bufferTokens !== undefined ||
      config.observation?.bufferActivation !== undefined ||
      config.reflection?.bufferActivation !== undefined;
    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

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Add observation: { bufferTokens: false } and remove bufferTokens, bufferActivation, and blockAfter settings
  2. Remove shareTokenBudget: true if async buffering is more important for your workload
  3. Wait for/upgrade to a version where the limitation is lifted

Example fix

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

Strategy: validation

Validate before calling

function assertShareTokenBudgetCompatible(c: ObservationalMemoryConfig): void {
  if (!c.shareTokenBudget) return;
  const o = c.observation ?? {};
  const asyncConfigured =
    (o.bufferTokens !== undefined && o.bufferTokens !== false) ||
    o.bufferActivation !== undefined || o.blockAfter !== undefined;
  if (asyncConfigured || o.bufferTokens !== false) {
    throw new Error('shareTokenBudget requires observation: { bufferTokens: false } and no other async buffering settings');
  }
}

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 };
    delete (config.observation as any).bufferActivation;
    delete (config.observation as any).blockAfter;
  } else throw err;
}

Prevention

When it happens

Trigger: new ObservationalMemory({ shareTokenBudget: true, observation: { bufferTokens: true } }) or setting shareTokenBudget with any explicit bufferTokens/bufferActivation/blockAfter values.

Common situations: Enabling token budget sharing on a config that already had async buffering tuned; combining feature flags from different docs examples.

Related errors


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