Skip to content

bug(undo-redo): QuotaExceededError when localStorage cap is exhausted by undo/redo snapshots #4737

@Sprexatura

Description

@Sprexatura

Summary

A QuotaExceededError: Failed to execute 'setItem' on 'Storage' can surface from various small Zustand-persisted stores (e.g., notification-storage, panel-editor-state) when a user has actively built workflows for some time. The stack trace points to the persist middleware's setItem call on whichever store happened to write next after the origin's localStorage cap was reached.

The store whose throw lands in monitoring is not the actual culprit — it's just the first victim after another store filled the origin's quota.

Root cause

workflow-undo-redo is persisted to localStorage and stores operation snapshots that include full block state. Capacity is MAX_STACKS=5 × DEFAULT_CAPACITY=100 = 500 ops. Active editing of multiple workflows quickly fills the per-stack capacity with snapshots that can be several KB each, occupying the bulk of the origin's ~5 MB localStorage budget.

Once the budget is exhausted, any other persisted Zustand store whose setItem is called next throws QuotaExceededError.

Reproduction (Chromium-based browser, ~5 MB origin cap)

  1. Open the workflow editor.
  2. Add an agent block and paste a large system prompt (e.g., 5 KB of text).
  3. Delete and re-add the block several times. Each cycle pushes batch-add-blocks and batch-remove-blocks operations whose snapshots include the full block state.
  4. Across a few workflows (up to 5 stacks as MAX_STACKS allows), the localStorage origin reaches the cap.
  5. Take any action that triggers another store's persist (e.g., select a block, dismiss a notification). The next setItem throws QuotaExceededError.

Measurement helper for the console:

```js
const sizes = Object.keys(localStorage).map(k => [k, localStorage.getItem(k)?.length ?? 0])
console.table(sizes.sort((a, b) => b[1] - a[1]))
```

shows workflow-undo-redo occupying the bulk of origin storage in the affected state.

Existing partial mitigations

Proposed fix

Migrate `workflow-undo-redo` to IndexedDB using the same `idb-keyval` pattern as `terminal-console-store` (PR #2812), including a one-time migration that copies any existing data and removes the legacy localStorage key on first module load. PR follows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions