mastra-ai/mastra · error · Error

No buffered reflection to swap

Error message

No buffered reflection to swap

What it means

swapBufferedReflectionToActive throws this when the resolved record exists but has no bufferedReflection, meaning there is nothing accumulated to promote into active observations. The library treats an empty buffer as an invalid swap request rather than a no-op, so callers don't silently lose track of reflection state.

Source

Thrown at packages/core/src/storage/domains/memory/inmemory.ts:1161

    }

    const existing = record.bufferedReflection || '';
    record.bufferedReflection = existing ? `${existing}\n\n${reflection}` : reflection;
    record.bufferedReflectionTokens = (record.bufferedReflectionTokens || 0) + tokenCount;
    record.bufferedReflectionInputTokens = (record.bufferedReflectionInputTokens || 0) + inputTokenCount;
    record.reflectedObservationLineCount = reflectedObservationLineCount;
    record.updatedAt = new Date();
  }

  async swapBufferedReflectionToActive(input: SwapBufferedReflectionToActiveInput): Promise<ObservationalMemoryRecord> {
    const { currentRecord } = input;
    const record = this.findObservationalMemoryRecordById(currentRecord.id);
    if (!record) {
      throw new Error(`Observational memory record not found: ${currentRecord.id}`);
    }

    if (!record.bufferedReflection) {
      throw new Error('No buffered reflection to swap');
    }

    const bufferedReflection = record.bufferedReflection;
    const reflectedLineCount = record.reflectedObservationLineCount ?? 0;

    // Split current activeObservations by the boundary line count.
    // Lines 0..reflectedLineCount were reflected on → replaced by bufferedReflection.
    // Lines after reflectedLineCount were added after reflection started → kept as-is.
    const currentObservations = record.activeObservations ?? '';
    const allLines = currentObservations.split('\n');
    const unreflectedLines = allLines.slice(reflectedLineCount);
    const unreflectedContent = unreflectedLines.join('\n').trim();

    // New activeObservations = bufferedReflection + unreflected observations
    const newObservations = unreflectedContent ? `${bufferedReflection}\n\n${unreflectedContent}` : bufferedReflection;

    // Create a new generation with the merged content.
    // tokenCount is computed by the processor using its token counter on the combined content.

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Only call swapBufferedReflectionToActive after updateBufferedReflection has stored a buffer for the record.
  2. Guard with a check on the record's bufferedReflection before swapping.
  3. Re-fetch the record to confirm the buffer hasn't already been consumed by a prior swap.
  4. Make the reflection workflow step idempotent so retries don't trigger a second swap.

Example fix

// before
await memory.swapBufferedReflectionToActive({ currentRecord, tokenCount });
// after
if (currentRecord.bufferedReflection) {
  await memory.swapBufferedReflectionToActive({ currentRecord, tokenCount });
}
Defensive patterns

Strategy: validation

Validate before calling

if (!currentRecord.bufferedReflection) {
  throw new Error('Refusing to swap: no buffered reflection accumulated');
}

Type guard

function hasBufferedReflection(r: ObservationalMemoryRecord): r is ObservationalMemoryRecord & { bufferedReflection: string } {
  return typeof r.bufferedReflection === 'string' && r.bufferedReflection.length > 0;
}

Prevention

When it happens

Trigger: Calling swapBufferedReflectionToActive before updateBufferedReflection has ever stored a buffer for the record, or calling it twice — the first swap clears bufferedReflection, so a second call with the same (now stale) currentRecord fails.

Common situations: Double-execution of a reflection workflow step (e.g. retry after a partial failure); race between the buffering and swapping stages of observational memory; calling the internal API manually in tests or custom processors without buffering first.

Related errors


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