diff --git a/API-INTERNAL.md b/API-INTERNAL.md
index b3cfeb90a..3a5cc6460 100644
--- a/API-INTERNAL.md
+++ b/API-INTERNAL.md
@@ -79,12 +79,17 @@ If the requested key is a collection, it will return an object with all the coll
Remove a key from Onyx and update the subscribers
retryOperation()
-Handles storage operation failures based on the error type:
+Handles storage operation failures based on the error class (see lib/storage/errors.ts).
+The connection layer (createStore) owns connection/transport recovery; this operation layer owns
+capacity recovery (eviction) so that a given failure is retried by exactly one layer:
-- Storage capacity errors: evicts data and retries the operation
-- Invalid data errors: logs an alert and throws an error
-- Non-retriable errors: logs an alert and resolves without retrying
-- Other errors: retries the operation
+- INVALID_DATA: logs an alert and throws (the same data will always fail).
+- TRANSIENT / FATAL: the connection layer already retried (transient) or exhausted its heal budget
+and alerted (fatal). Retrying here would only re-amplify, so we skip the write quietly.
+- CAPACITY: evicts the least recently accessed evictable key and retries, under a session-level
+circuit breaker (see lib/StorageCircuitBreaker.ts) that halts the loop once eviction stops making
+progress or failures storm — the per-operation budget alone cannot stop a session-wide storm.
+- UNKNOWN: bounded retry.
broadcastUpdate()
@@ -318,11 +323,16 @@ Remove a key from Onyx and update the subscribers
## retryOperation()
-Handles storage operation failures based on the error type:
-- Storage capacity errors: evicts data and retries the operation
-- Invalid data errors: logs an alert and throws an error
-- Non-retriable errors: logs an alert and resolves without retrying
-- Other errors: retries the operation
+Handles storage operation failures based on the error class (see lib/storage/errors.ts).
+The connection layer (createStore) owns connection/transport recovery; this operation layer owns
+capacity recovery (eviction) so that a given failure is retried by exactly one layer:
+- INVALID_DATA: logs an alert and throws (the same data will always fail).
+- TRANSIENT / FATAL: the connection layer already retried (transient) or exhausted its heal budget
+ and alerted (fatal). Retrying here would only re-amplify, so we skip the write quietly.
+- CAPACITY: evicts the least recently accessed evictable key and retries, under a session-level
+ circuit breaker (see lib/StorageCircuitBreaker.ts) that halts the loop once eviction stops making
+ progress or failures storm — the per-operation budget alone cannot stop a session-wide storm.
+- UNKNOWN: bounded retry.
**Kind**: global function
diff --git a/lib/OnyxUtils.ts b/lib/OnyxUtils.ts
index c88b2e170..ce552d653 100644
--- a/lib/OnyxUtils.ts
+++ b/lib/OnyxUtils.ts
@@ -6,8 +6,9 @@ import * as Logger from './Logger';
import type Onyx from './Onyx';
import cache, {TASK} from './OnyxCache';
import OnyxKeys from './OnyxKeys';
-import * as Str from './Str';
+import StorageCircuitBreaker from './StorageCircuitBreaker';
import Storage from './storage';
+import {StorageErrorClass, classifyStorageError} from './storage/errors';
import type {
CollectionKeyBase,
ConnectOptions,
@@ -49,26 +50,6 @@ const METHOD = {
CLEAR: 'clear',
} as const;
-// IndexedDB errors that indicate storage capacity issues where eviction can help
-const IDB_STORAGE_ERRORS = [
- 'quotaexceedederror', // Browser storage quota exceeded
-] as const;
-
-// SQLite errors that indicate storage capacity issues where eviction can help
-const SQLITE_STORAGE_ERRORS = [
- 'database or disk is full', // Device storage is full
-] as const;
-
-const STORAGE_ERRORS = [...IDB_STORAGE_ERRORS, ...SQLITE_STORAGE_ERRORS];
-
-// IndexedDB errors where retrying is futile because the underlying connection/store is broken.
-// The healing path (separate from retryOperation) is responsible for recovery.
-const IDB_NON_RETRIABLE_ERRORS = [
- 'internal error opening backing store', // LevelDB backing store is broken at the filesystem level
-] as const;
-
-const NON_RETRIABLE_ERRORS = [...IDB_NON_RETRIABLE_ERRORS];
-
// Max number of retries for failed storage operations
const MAX_STORAGE_OPERATION_RETRY_ATTEMPTS = 5;
@@ -425,7 +406,9 @@ function multiGet(keys: CollectionKeyBase[]): Promise