Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/storage/providers/IDBKeyValProvider/classifyError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ function classifyIDBError(error: unknown): ValueOf<typeof StorageErrorClass> {
return StorageErrorClass.INVALID_DATA;
}

// A queued File/Blob whose backing bytes are gone — the source OS file was modified, deleted, or
// renamed after being picked, so the structured clone fails at write time. Chromium reports it as
// InvalidBlob (Windows) or IOError (macOS). Retrying re-reads the same dead blob and can never succeed.
if (message.includes('failed to write blobs')) {
return StorageErrorClass.INVALID_DATA;
}

// Browser quota exceeded.
if (name.includes('quotaexceedederror') || message.includes('quotaexceedederror')) {
return StorageErrorClass.CAPACITY;
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/storage/providers/classifyErrorTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import classifyIDBError from '../../../../lib/storage/providers/IDBKeyValProvider/classifyError';
import {StorageErrorClass} from '../../../../lib/storage/errors';

describe('classifyIDBError', () => {
it.each([
// Dead File/Blob in the payload — the platform-specific dialects of "Failed to write blobs".
[new DOMException('Failed to write blobs (InvalidBlob)', 'DataError'), StorageErrorClass.INVALID_DATA],
[new DOMException('Failed to write blobs (IOError)', 'DataError'), StorageErrorClass.INVALID_DATA],
// Non-serializable payload.
[new TypeError("Failed to execute 'put' on 'IDBObjectStore': something could not be cloned."), StorageErrorClass.INVALID_DATA],
// Quota.
[new DOMException('The quota has been exceeded.', 'QuotaExceededError'), StorageErrorClass.CAPACITY],
// Backing-store corruption.
[new DOMException('Internal error opening backing store for indexedDB.open.', 'UnknownError'), StorageErrorClass.FATAL],
// Transient connection failures.
[new DOMException('Connection to Indexed Database server lost. Refresh the page to try again', 'UnknownError'), StorageErrorClass.TRANSIENT],
[new DOMException('IDB write transaction aborted without an error', 'AbortError'), StorageErrorClass.TRANSIENT],
// Anything else stays UNKNOWN.
[new Error('some brand new failure'), StorageErrorClass.UNKNOWN],
])('classifies %s as %s', (error, expectedClass) => {
expect(classifyIDBError(error)).toBe(expectedClass);
});
});
Loading