{"record":{"id":"f6dbaab9b44ff9f0","repo":"mastra-ai/mastra","slug":"sharetokenbudget-requires-async-buffering-to-be-di-f6dbaa","errorCode":null,"errorMessage":"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\nAsync buffering is enabled by default — this opt-out is only needed when using shareTokenBudget.","messagePattern":"shareTokenBudget requires async buffering to be disabled \\(this is a temporary limitation\\)\\. Add observation: (.+?) to your config:\n\n  observationalMemory: (.+?),\n  \\}\n\nAsync buffering is enabled by default — this opt-out is only needed when using shareTokenBudget\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/observational-memory.ts","lineNumber":563,"sourceCode":"    const asyncBufferingDisabled =\n      config.observation?.bufferTokens === false || (config.scope === 'resource' && !userExplicitlyConfiguredAsync);\n\n    // shareTokenBudget is not yet compatible with async buffering (temporary limitation).\n    // To use shareTokenBudget, users must explicitly disable buffering.\n    if (isSharedBudget && !asyncBufferingDisabled) {\n      const common =\n        `shareTokenBudget requires async buffering to be disabled (this is a temporary limitation). ` +\n        `Add observation: { bufferTokens: false } to your config:\\n\\n` +\n        `  observationalMemory: {\\n` +\n        `    shareTokenBudget: true,\\n` +\n        `    observation: { bufferTokens: false },\\n` +\n        `  }\\n`;\n      if (userExplicitlyConfiguredAsync) {\n        throw new Error(\n          common + `\\nRemove any other async buffering settings (bufferTokens, bufferActivation, blockAfter).`,\n        );\n      } else {\n        throw new Error(\n          common + `\\nAsync buffering is enabled by default — this opt-out is only needed when using shareTokenBudget.`,\n        );\n      }\n    }\n\n    const observationActivateAfterIdle = config.observation?.activateAfterIdle ?? config.activateAfterIdle;\n    const observationActivateAfterIdlePath =\n      config.observation?.activateAfterIdle !== undefined ? 'observation.activateAfterIdle' : 'activateAfterIdle';\n\n    // Resolve observation config with defaults\n    this.observationConfig = {\n      model: observationModel,\n      // When shared budget, store as range: min = base threshold, max = total budget\n      // This allows messages to expand into unused observation space\n      messageTokens: isSharedBudget ? { min: messageTokens, max: totalBudget } : messageTokens,\n      shareTokenBudget: isSharedBudget,\n      modelSettings: {\n        temperature:","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/observational-memory.ts#L545-L581","documentation":"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.","triggerScenarios":"new ObservationalMemory({ shareTokenBudget: true, ... }) with no explicit observation.bufferTokens: false — the implicit default async buffering triggers the error.","commonSituations":"First-time adoption of shareTokenBudget without reading the buffering caveat; minimal configs copied from older examples that predate the default buffering.","solutions":["Set observation: { bufferTokens: false } alongside shareTokenBudget: true","Remove shareTokenBudget: true if you want to keep default async buffering","Disable async buffering at the config-construction site where shareTokenBudget is toggled, not ad hoc"],"exampleFix":"// before\nnew ObservationalMemory({ model, shareTokenBudget: true })\n// after\nnew ObservationalMemory({\n  model,\n  shareTokenBudget: true,\n  observation: { bufferTokens: false }\n})","handlingStrategy":"validation","validationCode":"function assertShareTokenBudgetOptOut(c: ObservationalMemoryConfig): void {\n  if (c.shareTokenBudget && c.observation?.bufferTokens !== false) {\n    throw new Error('shareTokenBudget requires observation: { bufferTokens: false } (async buffering is on by default)');\n  }\n}","typeGuard":"function isShareTokenBudgetConfig(c: ObservationalMemoryConfig): boolean {\n  return !c.shareTokenBudget || c.observation?.bufferTokens === false;\n}","tryCatchPattern":"try {\n  const mem = new ObservationalMemory(config);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('shareTokenBudget requires async buffering')) {\n    config.observation = { ...config.observation, bufferTokens: false };\n  } else throw err;\n}","preventionTips":["Always pair shareTokenBudget: true with observation: { bufferTokens: false }","Remember async buffering is the default — absence of bufferTokens does not mean it's off","Build ObservationalMemory through one factory function that enforces this pairing"],"tags":["config","validation","incompatible-options","tokens"],"backgroundTag":"conflicting-config-options","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}