ruvnet/ruflo · warning

Too many events to replay (${events.length}). Consider creat

Error message

Too many events to replay (${events.length}). Consider creating a snapshot.

What it means

StateReconstructor refuses to rebuild an aggregate when the number of events to apply after the latest snapshot exceeds options.maxEventsToReplay. Replay cost grows linearly with event count, so the guard stops expensive rebuilds and points you at snapshotting: with useSnapshots enabled and a reasonable snapshotInterval, rehydration starts from a recent snapshot and the replay count stays small. It typically fires for long-lived aggregates with no snapshot yet or a snapshot interval larger than the replay ceiling.

Source

Thrown at v3/@claude-flow/shared/src/events/state-reconstructor.ts:76

    factory: (id: string) => T
  ): Promise<T> {
    const aggregate = factory(aggregateId);

    // Try to load from snapshot first
    if (this.options.useSnapshots) {
      const snapshot = await this.eventStore.getSnapshot(aggregateId);
      if (snapshot) {
        this.applySnapshot(aggregate, snapshot);
      }
    }

    // Get events after snapshot version (or all if no snapshot)
    const events = await this.eventStore.getEvents(aggregateId, aggregate.version + 1);

    // Apply events
    for (const event of events) {
      if (events.length > this.options.maxEventsToReplay) {
        throw new Error(`Too many events to replay (${events.length}). Consider creating a snapshot.`);
      }

      aggregate.apply(event);
    }

    // Create snapshot if interval reached
    if (this.options.useSnapshots && aggregate.version % this.options.snapshotInterval === 0) {
      await this.createSnapshot(aggregate);
    }

    return aggregate;
  }

  /**
   * Reconstruct state at a specific point in time
   */
  async reconstructAtTime<T extends AggregateRoot>(
    aggregateId: string,

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Create a snapshot for the affected aggregate (createSnapshot / enable useSnapshots) so future rehydrations start from a recent version
  2. Lower options.snapshotInterval so snapshots are taken more frequently than maxEventsToReplay events accumulate
  3. If the hardware genuinely supports it, raise options.maxEventsToReplay deliberately as a tuning decision — then snapshot soon after

Example fix

// before
const recon = new StateReconstructor(store, factory, {
  useSnapshots: false,
  maxEventsToReplay: 1000,
});
await recon.rebuild(orderId); // long history -> throws

// after
const recon = new StateReconstructor(store, factory, {
  useSnapshots: true,
  snapshotInterval: 500,
  maxEventsToReplay: 1000,
});
await recon.rebuild(orderId); // snapshots keep replay under the limit
Defensive patterns

Strategy: fallback

Validate before calling

const recon = new StateReconstructor(eventStore, aggregateFactory, {
  useSnapshots: true,
  snapshotInterval: 500,
  maxEventsToReplay: 1000,
});
// keep snapshotInterval well below maxEventsToReplay so this never trips

Try / catch

try {
  aggregate = await recon.rebuild(aggregateId);
} catch (e) {
  if (e instanceof Error && e.message.includes('Too many events to replay')) {
    // fallback: rebuild with a raised ceiling, snapshot immediately, then restore the normal limit
    const tolerant = new StateReconstructor(eventStore, aggregateFactory, {
      useSnapshots: true,
      snapshotInterval: 100,
      maxEventsToReplay: Number.MAX_SAFE_INTEGER,
    });
    aggregate = await tolerant.rebuild(aggregateId);
  } else throw e;
}

Prevention

When it happens

Trigger: Rehydrating an aggregate whose post-snapshot event count exceeds maxEventsToReplay; useSnapshots disabled in StateReconstructorOptions; snapshotInterval set so high (or event volume so bursty) that more than maxEventsToReplay events accumulate between snapshots; first rehydrate of an old aggregate created before snapshots existed.

Common situations: High-write event-sourced aggregates with sparse snapshots; snapshots turned off for simplicity then hitting the ceiling as history grows; bulk rehydration jobs (rebuilding all aggregates) tripping the limit on the oldest ones.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/4184efd0ca7cb10c. Report an issue: GitHub.