Skip to content

Error Handling & System Limits ​

To guarantee fast startup, predictable memory usage on mobile browsers, and a compact footprint (~19 KB gzipped / ~51 KB raw Wasm core), WebDB enforces clear boundaries and throws strongly-typed error classes that you can catch in your application code.


1. Practical System Limits ​

AreaLimitNotes & How to Handle
Maximum Row Size2,048 bytes (2 KB)Serialized size of a single row (columns + strings/blobs) cannot exceed 2 KB. Store large files/images in OPFS/Blob storage and save their URL or file key in WebDB.
Identifier Length64 charactersMaximum length for table names, column names, and index names (matches PostgreSQL & MySQL).
Tables per DatabaseUnlimited (16 on Page 1 + 31/overflow page)Page 1 stores 16 tables; additional tables chain automatically via NEXT_CATALOG_PAGE_ID overflow catalog pages.
Columns per Table256 columnsSupports 1 to 256 columns per table.
Secondary IndexesUnlimited (8 on Page 1 + 31/overflow page)Primary key indexes are embedded in TableDescriptor; secondary indexes store 8 on Page 1 and chain via NEXT_INDEX_CATALOG_PAGE_ID (up to 8 columns per index).
ORDER BY Columns8 columnsMaximum columns in a multi-column .orderBy() clause.
GROUP BY Columns8 columnsMaximum columns in a multi-column .groupBy() clause.
Where IN List Size10,000 valuesMaximum array length or subquery result set passed to .whereIn() or .whereNotIn().
Subquery Nesting Depth7 levelsMaximum nesting depth for subqueries in from(), where(), having(), and select().
Joined Tables per Query16 cursorsSupports up to 16 concurrent table/index cursors in a single query.
Query Memory Ceiling16 MB (default)Used for unindexed ORDER BY sorts and GROUP BY hash tables. Increase via WebDB.open({ maxQueryMemory: 64 * 1024 * 1024 }) if needed.
Idle Transaction Timeout30 secondsOpen transactions that remain idle for 30s automatically roll back so they cannot deadlock other tabs.

2. Typed Error Classes ​

All custom error classes are exported directly from @ahmadmoussawi/webdb so you can check them using instanceof:

typescript
import {
  UniqueConstraintViolationError,
  NotNullConstraintError,
  RowSizeLimitExceededError,
  TableNotFoundError,
} from "@ahmadmoussawi/webdb";

try {
  await db.insert("users", {
    id: existingUserId,
    email: "duplicate@example.com",
  });
} catch (err) {
  if (err instanceof UniqueConstraintViolationError) {
    alert("An account with this ID or email already exists.");
  } else if (err instanceof NotNullConstraintError) {
    alert("Please fill in all required fields.");
  } else if (err instanceof RowSizeLimitExceededError) {
    alert("Profile text is too long (maximum 2 KB per record).");
  } else {
    throw err;
  }
}

Complete Error Reference ​

Error ClassWhen It Is Thrown
UniqueConstraintViolationErrorInserting or updating a duplicate value on a primaryKey: true column or { unique: true } index.
NotNullConstraintErrorInserting null/undefined into a notNull: true column, or calling addColumn with notNull: true on a populated table without a defaultValue.
RowSizeLimitExceededErrorInserting or updating a row whose serialized binary size exceeds 2,048 bytes.
TableNotFoundErrorQuerying, mutating, or inspecting a table name that does not exist.
TableAlreadyExistsErrorCalling createTable() or renameTable() with a name that already exists.
ColumnNotFoundErrorReferencing a non-existent column in renameColumn, dropColumn, createIndex, or queries.
ColumnAlreadyExistsErrorDefining duplicate column names in createTable, addColumn, or renameColumn.
CannotDropColumnErrorAttempting to drop a PRIMARY KEY column or the only remaining column of a table.
IndexNotFoundErrorCalling dropIndex() with an index name that does not exist.
IndexAlreadyExistsErrorCalling createIndex() with a name that already exists.
IdentifierTooLongErrorProviding a table, column, or index name longer than 64 characters.
TooManyTablesErrorCreating more than 16 tables.
TooManyColumnsErrorCreating or altering a table to have more than 256 columns.
TooManyIndexesErrorCreating more than 8 indexes on Page 1.
TooManyOrderByColumnsErrorOrdering by more than 8 columns.
TooManyGroupByColumnsErrorGrouping by more than 8 columns.
TooManyCursorsErrorCompiling a query that requires more than 16 cursors (e.g. >16 joined tables).
TooManyRegistersErrorCompiling an expression tree that exceeds 64 VM registers.
SubqueryNestingTooDeepErrorNesting subqueries beyond the maximum depth of 7 levels.
AggregateNotAllowedInWhereErrorUsing count(), sum(), avg(), min(), or max() inside .where() instead of .having().
UnknownFunctionErrorCalling a function name in an expression that is neither built-in nor registered via db.registerFunction().
QueryArenaExhaustedErrorAn unindexed sort or hash aggregation exceeded maxQueryMemory (increase maxQueryMemory in WebDB.open() or add an index).
QueryTimeoutErrorA query exceeded the VM instruction cycle safety limit.
InvalidDatabaseErrorPassing a malformed or truncated buffer to db.importBinary().
CorruptPageErrorA database page failed IEEE 802.3 CRC32 checksum verification on read or importBinary().
CorruptWalHeaderError / CorruptWalFrameErrorCorrupted WAL data encountered when validating WAL frames.

Released under the MIT License.