sqlite3
semver
>=5.0.3postconditions35functions15last verified2026-06-23coverage score71%Postconditions — what we check
- run · syntax-errorerrorWhenSQL syntax errorThrows
Error with message containing 'SQLITE_ERROR' or syntax detailsRequired handlingCaller MUST validate SQL syntax before execution. DO NOT retry - indicates SQL syntax error. Error message contains details about syntax issue.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - run · constraint-violationerrorWhenUnique constraint, foreign key, or NOT NULL violationThrows
Error with 'SQLITE_CONSTRAINT' codeRequired handlingCaller MUST handle constraint violations: - UNIQUE constraint: error.message contains constraint details - FOREIGN KEY: foreign key constraint violation - NOT NULL: required field missing DO NOT retry without fixing data.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - run · database-lockederrorWhenDatabase is locked by another process or transactionThrows
Error with 'SQLITE_BUSY' codeRequired handlingCaller MUST handle database locked errors. SQLite uses file-level locking. Implement retry with exponential backoff. Consider using WAL mode for better concurrency.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - run · table-not-founderrorWhenTable does not existThrows
Error with message 'no such table'Required handlingCaller MUST verify table exists before executing queries. DO NOT retry - indicates schema mismatch or missing migration.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - run · disk-fullerrorWhenDisk is full or quota exceededThrows
Error with 'SQLITE_FULL' codeRequired handlingCaller MUST handle disk full errors. Check available disk space. Alert operations - this is a system-level issue.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - get · syntax-errorerrorWhenSQL syntax errorThrows
Error with 'SQLITE_ERROR' or syntax messageRequired handlingCaller MUST validate SQL syntax. DO NOT retry - fix SQL syntax.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - get · database-lockederrorWhenDatabase is lockedThrows
Error with 'SQLITE_BUSY' codeRequired handlingCaller MUST handle database locked errors. Implement retry with exponential backoff.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - all · syntax-errorerrorWhenSQL syntax errorThrows
Error with 'SQLITE_ERROR' or syntax messageRequired handlingCaller MUST validate SQL syntax. DO NOT retry - fix SQL syntax.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - all · database-lockederrorWhenDatabase is lockedThrows
Error with 'SQLITE_BUSY' codeRequired handlingCaller MUST handle database locked errors. Implement retry with exponential backoff.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - all · memory-errorerrorWhenOut of memory for large result setsThrows
Error with 'SQLITE_NOMEM' codeRequired handlingCaller MUST handle out of memory errors. Use pagination for large result sets. Consider using each() iterator instead of all().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - exec · syntax-errorerrorWhenSQL syntax error in any statementThrows
Error with 'SQLITE_ERROR' or syntax messageRequired handlingCaller MUST validate SQL syntax. exec() does not support parameterized queries. NEVER use with user input - SQL injection risk.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - exec · constraint-violationerrorWhenConstraint violation in any statementThrows
Error with 'SQLITE_CONSTRAINT' codeRequired handlingCaller MUST handle constraint violations. DO NOT retry without fixing data.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - prepare · syntax-errorerrorWhenSQL syntax error in statementThrows
Error with 'SQLITE_ERROR' or syntax messageRequired handlingCaller MUST validate SQL syntax. DO NOT retry - fix SQL syntax.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - each · each-completion-error-ignorederrorWhenSQL syntax error, SQLITE_BUSY, or SQLITE_CONSTRAINT occurs and the completion callback (second callback argument) is omitted or doesn't check its err parameter.Throws
Error passed to row callback and completion callback as first argument. If row callback ignores err, the database error is silently swallowed and the application proceeds with partial or zero results.Required handlingCaller MUST check the err parameter in both the row callback AND the completion callback. Pattern: db.each(sql, params, (err, row) => { if (err) throw err; /* use row */ }, (err, count) => { if (err) { /* handle */ } } ); Omitting the completion callback or ignoring its err causes silent failures where query errors are swallowed.costhighin prodsilent failureusers seelost datavisibilitysilent - each · each-syntax-errorerrorWhenSQL syntax error in the queryThrows
Error with 'SQLITE_ERROR' or syntax details passed to row callbackRequired handlingCaller MUST check err in row callback. DO NOT retry — indicates SQL syntax error. Error message contains details about syntax issue.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - close · close-unfinalised-statementserrorWhenDatabase.close() called while prepared statements created with Database.prepare() are still active (not finalized).Throws
Error with message "SQLITE_BUSY: unable to close due to unfinalised statements" passed to callback. errno = sqlite3.BUSY.Required handlingCaller MUST call stmt.finalize() on all prepared statements before calling db.close(). Pattern: stmt.finalize(() => db.close(callback)); Failing to finalize statements causes db.close() to fail silently if no callback is provided, leaking the database connection.costmediumin proddegraded serviceusers seedegraded performancevisibilitysilent - close · close-already-closedwarningWhenDatabase.close() called a second time after the database is already closed.Throws
Error with errno === sqlite3.MISUSE passed to callback. SQLITE_MISUSE indicates the database connection was used in an undefined/unsupported way.Required handlingCaller MUST track database open/closed state and only close once. Do not call db.close() multiple times. Wrap in a guard: if (dbIsOpen) { db.close(() => { dbIsOpen = false; }); }costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - loadExtension · loadextension-file-not-founderrorWhenExtension file path does not exist, has wrong file extension, or the .so/.dll/.dylib file cannot be opened by the OS.Throws
Error with message containing file path and OS error (e.g., "no such file or directory") passed to callback. The database remains open and usable, but without the extension.Required handlingCaller MUST check err in the loadExtension callback. Pattern: db.loadExtension('./myext', (err) => { if (err) throw new Error(`Extension load failed: ${err.message}`); }); Failing to check err causes the application to proceed without the extension, leading to "no such function" SQL errors later.costmediumin proddelayed failureusers seeservice unavailablevisibilitysilent - loadExtension · loadextension-security-disabledwarningWhenSQLite was compiled with SQLITE_OMIT_LOAD_EXTENSION or extension loading was disabled via sqlite3_db_config() SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION.Throws
Error with message "not authorized" or "not implemented" passed to callback. Common in restricted environments (embedded systems, security-hardened builds).Required handlingCaller MUST handle this error gracefully. Check at application startup if extensions are available before depending on them.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - backup · backup-cantopen-destinationerrorWhenDestination file path is in a directory that doesn't exist, or the process lacks write permission to the destination path.Throws
Error with SQLITE_CANTOPEN passed to the step() callback or the initial backup callback. errno = sqlite3.CANTOPEN.Required handlingCaller MUST check that the destination directory exists and is writable before calling db.backup(). Check err in both the backup callback and step() callbacks. const backup = db.backup('path/to/backup.db', (err) => { if (err) throw err; // destination not accessible });costhighin prodimmediate exceptionusers seelost datavisibilityvisible - backup · backup-misuse-after-finishwarningWhenbackup.step() is called after backup.finish() has been called (i.e., after the backup is already complete or abandoned).Throws
Error with message "Backup is already finished" and errno === sqlite3.MISUSE passed to the step() callback.Required handlingCaller MUST check backup.completed or backup.failed before calling step() again. Do not call step() after the backup is finished. Track completion state via backup.completed property.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8] - finalize · finalize-not-callederrorWhenA Statement created via db.prepare(sql) is never finalized — the statement object goes out of scope or the database is closed without stmt.finalize() being called. This is the #1 cause of SQLITE_BUSY errors on db.close() and resource leaks in long-running processes.Throws
Indirect: a subsequent db.close() callback receives Error with message "SQLITE_BUSY: unable to close due to unfinalised statements" (errno = sqlite3.BUSY). The leaked native sqlite3_stmt holds a row cursor and a transaction handle until garbage-collected.Required handlingCaller MUST call stmt.finalize() exactly once on every Statement returned by db.prepare(). Pattern: const stmt = db.prepare(sql); stmt.run(params, (err) => { stmt.finalize(); }); OR use db.run/get/all which auto-finalize the internal statement. For long-running prepared statements (loops, batches), finalize after the last execution.costmediumin proddegraded serviceusers seedegraded performancevisibilitysilent - finalize · finalize-callback-error-ignorederrorWhenstmt.finalize(callback) is called with a callback that does not check its err parameter. The native finalize call can fail when deferred constraint checks fire at finalization time (e.g. FK constraint that was deferred to end-of-statement) or when the statement is finalized mid-transaction and the rollback path itself errors.Throws
Error passed to callback as first argument. The Error.message contains the SQLITE_* error code and message. The most common cases are SQLITE_CONSTRAINT (deferred constraint failure) and SQLITE_MISUSE (double-finalize on an already-finalized statement).Required handlingCaller MUST check the err parameter in finalize's callback. Pattern: stmt.finalize((err) => { if (err) { // Deferred constraint failed OR statement already finalized throw new Error(`Finalize failed: ${err.message}`); } }); Without this check, deferred constraint violations corrupt data silently and double-finalize bugs go undetected.costhighin prodsilent failureusers seelost datavisibilitysilent - Statement.run · statement-run-callback-error-ignorederrorWhenstmt.run([params,] callback) where the callback does not check its err parameter. Unlike db.run (which auto-finalizes a one-off statement), a prepared Statement is reused — a swallowed error leaves stale binding state and produces wrong results on subsequent calls.Throws
Error passed to callback as first argument. Includes binding errors (SQLITE_RANGE for too many params, SQLITE_MISMATCH for type errors), constraint violations (SQLITE_CONSTRAINT), and database-locked errors (SQLITE_BUSY). On error, `this.lastID` and `this.changes` are undefined.Required handlingCaller MUST check the err parameter. Pattern: const stmt = db.prepare('INSERT INTO users VALUES (?, ?)'); for (const user of users) { stmt.run([user.id, user.name], function(err) { if (err) { stmt.finalize(); throw new Error(`Insert ${user.id} failed: ${err.message}`); } // this.lastID, this.changes available here }); } stmt.finalize(); Ignoring err in a batch loop silently skips failed inserts and produces incomplete writes — a classic silent-data-loss bug.costhighin prodsilent failureusers seelost datavisibilitysilentSources[1] - Statement.run · statement-run-without-finalize-in-loopwarningWhenA prepared statement is run in a loop or repeatedly via stmt.run() but never finalized. Each iteration leaves the statement bound to the latest params; the underlying sqlite3_stmt accumulates state and eventually triggers SQLITE_BUSY on db.close.Throws
Indirect: leaked sqlite3_stmt holds a transaction handle. db.close() callback receives "SQLITE_BUSY: unable to close due to unfinalised statements". On a long-running server, this leaks native memory.Required handlingAlways finalize after the last run(). Pattern: const stmt = db.prepare(sql); try { for (const row of rows) { await new Promise((resolve, reject) => stmt.run(row, err => err ? reject(err) : resolve(null)) ); } } finally { stmt.finalize(); }costmediumin proddegraded serviceusers seedegraded performancevisibilitysilentSources[1] - map · map-callback-error-ignorederrorWhendb.map(sql, [params,] callback) where callback does not check err. Underlying .all() can fail on SQL syntax, SQLITE_BUSY, or SQLITE_NOMEM for large result sets — these errors are delivered to map's callback but the failure mode (silent {} result) is visually indistinguishable from "query succeeded but returned no rows".Throws
Error passed to callback's first argument. Same error profile as Database#all (SQLITE_ERROR, SQLITE_BUSY, SQLITE_NOMEM). On error the second argument (result object) is undefined.Required handlingCaller MUST check err. Pattern: db.map('SELECT id, name FROM users', (err, usersById) => { if (err) throw new Error(`Map query failed: ${err.message}`); // usersById is { 1: 'alice', 2: 'bob' } }); Ignoring err means a failed query is indistinguishable from a query returning no rows — a downstream lookup against `usersById[id]` will return undefined and the caller will conclude "user not found" instead of surfacing the database error.costhighin prodsilent failureusers seelost datavisibilitysilentSources[1] - map · map-key-collision-silent-overwritewarningWhenThe first column of the SELECT returns duplicate values across rows. Statement#map keys the result object by the first column; later rows OVERWRITE earlier rows that share the same key. The callback receives err=null and a result object with fewer entries than the row count, and no error or warning is logged.Throws
No error — this is silent data loss by design of the .map() transform. The result object contains a subset of rows; the caller has no signal that overwrites occurred.Required handlingCaller MUST guarantee the first column is unique for the query, OR use db.all() to get a row array and group manually. Pattern (safe): // BAD — map silently collides: db.map('SELECT user_id, action FROM events', (err, actionsByUser) => { // Last action per user only — other actions silently lost }); // GOOD — use .all() and group explicitly: db.all('SELECT user_id, action FROM events', (err, rows) => { if (err) throw err; const actionsByUser = {}; for (const r of rows) { (actionsByUser[r.user_id] ||= []).push(r.action); } });costmediumin prodsilent failureusers seelost datavisibilitysilentSources[1] - Database · database-open-cantopenerrorWhenConstructor called with a filename that does not exist when mode does NOT include OPEN_CREATE, OR filename points to a directory, OR filename path is a broken symlink with OPEN_NOFOLLOW, OR the parent directory does not exist, OR the process lacks search permission on an ancestor directory.Throws
Error with errno === sqlite3.CANTOPEN (14) passed to the constructor callback. The Database object is returned but is unusable — subsequent operations will fail with the same error or emit "error" events.Required handlingCaller MUST check err in the constructor callback. Pattern: const db = new sqlite3.Database('/path/to/data.db', sqlite3.OPEN_READWRITE, (err) => { if (err) { // err.errno === sqlite3.CANTOPEN means file missing / inaccessible throw new Error(`Failed to open database at /path/to/data.db: ${err.message}`); } }); Failing to check err is catastrophic: the application proceeds with an unusable db handle. Every subsequent db.run/get/all silently emits its own error event, and unless an 'error' listener is registered the process crashes via the EventEmitter "error" default behavior. This is one of the most common production silent-deploy failures with sqlite3 — a missing data file in production with no clear error chain.costhighin prodsilent failureusers seeservice unavailablevisibilitysilent - Database · database-open-permerrorWhenConstructor called with a filename whose owning user/group lacks the requested mode permissions (READONLY needs read; READWRITE needs both read and write). Most common when application runs as a non-root user but the data file was created by a different user or has restrictive umask, or when the parent directory lacks write permission and OPEN_CREATE is requested.Throws
Error with errno === sqlite3.PERM (3) passed to the constructor callback. Message typically contains "SQLITE_PERM: access permission denied".Required handlingCaller MUST check err and surface a clear permission error. Pattern: const db = new sqlite3.Database(file, (err) => { if (err && err.errno === sqlite3.PERM) { throw new Error(`No permission to open ${file} — check file ownership and process user`); } if (err) throw err; }); In containerized deployments (Docker, Kubernetes), this is one of the most common errors at first startup when the data volume is mounted with a different uid/gid than the app container's user.costhighin prodsilent failureusers seeservice unavailablevisibilitysilent - Database · database-open-notadberrorWhenConstructor called with a filename that exists and is readable but is not a SQLite database file. The file's first 16 bytes do not match the SQLite magic header ("SQLite format 3\0"). Common when an application accidentally points at a backup .tar.gz, a text file, a truncated download, or a previous-format SQLite file (SQLite 2.x).Throws
Error with errno === sqlite3.NOTADB (26) passed to constructor callback. Message contains "SQLITE_NOTADB: file is not a database".Required handlingCaller MUST check err in the constructor callback. Pattern: const db = new sqlite3.Database(file, (err) => { if (err && err.errno === sqlite3.NOTADB) { // File exists but is not a SQLite database — wrong path or corrupted download throw new Error(`${file} is not a SQLite database file`); } if (err) throw err; }); DO NOT retry — NOTADB is deterministic; the file content needs to change before this will succeed.costmediumin prodsilent failureusers seeservice unavailablevisibilitysilent - Database · database-open-corrupterrorWhenConstructor called with a filename that IS a SQLite database but whose internal pages have been damaged. Typically caused by partial writes (process killed during a write), filesystem corruption, copying a hot database file without proper backup API, or running out of disk space mid-write. The error may surface either at open time or on the first read/write that touches the corrupted page.Throws
Error with errno === sqlite3.CORRUPT (11) passed to the constructor callback OR to a subsequent operation's callback. Message contains "SQLITE_CORRUPT: database disk image is malformed".Required handlingCaller MUST check err in the constructor callback AND treat CORRUPT as unrecoverable for the affected database. Pattern: const db = new sqlite3.Database(file, (err) => { if (err && err.errno === sqlite3.CORRUPT) { // Database is damaged — restore from backup, do NOT continue writing throw new Error(`Database ${file} is corrupt; restore from backup`); } if (err) throw err; }); DO NOT continue writing to a CORRUPT database — subsequent writes can amplify the damage. Application should fail fast and alert operators to restore from a backup or rebuild the database. This is why production systems should run `PRAGMA integrity_check` periodically and use WAL mode + sqlite_backup() for hot backups.costhighin prodsilent failureusers seelost datavisibilitysilent - Statement.get · statement-get-callback-error-ignorederrorWhenstmt.get([params,] callback) where the callback does not check its err parameter. Same error profile as Database#get (SQLITE_ERROR for syntax, SQLITE_BUSY for lock contention, SQLITE_RANGE for bad parameter binding, SQLITE_MISMATCH for type mismatch) BUT the row parameter is undefined on error — accessing properties of undefined throws TypeError downstream and corrupts the loop state of a long- lived prepared statement.Throws
Error passed to callback as first argument. On error the second argument (row) is undefined. The statement is NOT automatically finalized — the row cursor remains in an indeterminate state.Required handlingCaller MUST check err before using row. Pattern: const stmt = db.prepare('SELECT * FROM users WHERE id = ?'); for (const id of ids) { await new Promise((resolve, reject) => { stmt.get([id], (err, row) => { if (err) { stmt.finalize(); return reject(err); } if (!row) { // No row matched — distinct from error return resolve(null); } resolve(row); }); }); } stmt.finalize(); Ignoring err in a lookup loop both silently swallows the actual database error AND fails to distinguish "row not found" (row === undefined, err === null) from "query failed" (row === undefined, err !== null) — they're indistinguishable to a caller that ignores err.costhighin prodsilent failureusers seelost datavisibilitysilent - Statement.get · statement-get-leaves-database-lockedwarningWhenstmt.get() is called once on a prepared statement and the underlying sqlite3_stmt is left mid-cursor (not finalized, not reset, not iterated to completion). The Statement#get documentation explicitly warns: "Using this method can leave the database locked, as the database awaits further calls to Statement#get to retrieve subsequent rows."Throws
Indirect: the underlying database connection holds a row cursor lock. Subsequent writes from the same connection may proceed, but ANOTHER process attempting to write to the same database file receives SQLITE_BUSY. db.close() will fail with "SQLITE_BUSY: unable to close due to unfinalised statements".Required handlingCaller MUST either finalize the statement after the last get(), reset it for reuse, or iterate to completion. Pattern (single lookup): const stmt = db.prepare('SELECT * FROM users WHERE id = ?'); stmt.get([id], (err, row) => { stmt.finalize(); // Release the cursor before exiting if (err) throw err; handleRow(row); }); Or for reuse across many lookups, finalize once after the last call. Long-lived servers that prepare-and-leak statements eventually fail to write or close the database.costmediumin proddegraded serviceusers seedegraded performancevisibilitysilentSources[1] - Statement.each · statement-each-completion-error-ignorederrorWhenstmt.each([params,] rowCallback [, completionCallback]) is invoked where either (a) the completion callback is omitted entirely, or (b) the completion callback's err parameter is not checked. Unlike Database#each — which auto-finalizes the underlying one-off statement — a prepared Statement is reused, so a swallowed error leaves the cursor mid-iteration AND silently drops query errors. The row callback also receives err on per-row failures; if it ignores err while accessing row.<field>, downstream code corrupts on undefined.Throws
Error passed to row callback as first argument on per-row failures AND passed to completion callback as first argument on overall query failures (SQLITE_ERROR for syntax, SQLITE_BUSY for lock contention, SQLITE_CONSTRAINT for constraint violations during read locks, SQLITE_NOMEM for large result sets). On error the row argument is undefined and the count argument in the completion callback is also undefined or partial.Required handlingCaller MUST check err in BOTH callbacks AND always finalize after iteration completes. Pattern: const stmt = db.prepare('SELECT id, name FROM users WHERE active = ?'); stmt.each([true], (err, row) => { if (err) throw new Error(`Row read failed: ${err.message}`); processUser(row); }, (err, count) => { stmt.finalize(); // ALWAYS finalize after iteration if (err) throw new Error(`Query failed after ${count} rows: ${err.message}`); } ); Omitting the completion callback is the most common bug: the query error is delivered nowhere and the caller proceeds as if iteration completed cleanly. This is structurally identical to the each- completion-error-ignored pattern on Database#each (id: each-completion-error-ignored on the `each` function), EXCEPT that Statement.each ALSO leaks the cursor lock — see the companion postcondition statement-each-cursor-not-released.costhighin prodsilent failureusers seelost datavisibilitysilent - Statement.each · statement-each-cursor-not-releasedwarningWhenstmt.each() is invoked but the underlying sqlite3_stmt is never finalized or reset after iteration completes (or aborts on error). The wiki is explicit: "Using this method can leave the database locked... To inform the database that you are finished retrieving rows, you should either finalize (with Statement#finalize) or reset (with Statement#reset) the statement." Unlike Database.each (which finalizes the auto-created statement internally), a developer-prepared Statement holds the row cursor until explicitly released. In a long- running server this leaks native sqlite3_stmt handles and eventually fails db.close() with SQLITE_BUSY.Throws
Indirect: the underlying database connection holds a row cursor lock. Other connections to the same database file receive SQLITE_BUSY on write attempts. db.close() will fail with "SQLITE_BUSY: unable to close due to unfinalised statements". The native sqlite3_stmt accumulates in the process address space until garbage-collected.Required handlingCaller MUST call stmt.finalize() or stmt.reset() after iteration. Pattern (single-shot iteration): const stmt = db.prepare('SELECT * FROM logs WHERE level = ?'); stmt.each( ['error'], (err, row) => { if (err) { stmt.finalize(); // Release on error throw err; } handleRow(row); }, (err, count) => { stmt.finalize(); // Release on completion if (err) throw err; } ); Pattern (reuse across multiple param sets): const stmt = db.prepare(sql); try { for (const params of paramSets) { await iterateOnce(stmt, params); // wraps each + reset } } finally { stmt.finalize(); } Failure to release the cursor is the most common cause of the "SQLITE_BUSY: unable to close" error on graceful shutdown.costmediumin proddegraded serviceusers seedegraded performancevisibilitysilentSources[1]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]github.com/TryGhost/node-sqlite3https://github.com/TryGhost/node-sqlite3/wiki/API
- [2]sqlite.org/rescode.htmlhttps://www.sqlite.org/rescode.html
- [3]sqlite.org/lockingv3.htmlhttps://www.sqlite.org/lockingv3.html
- [4]raw.githubusercontent.com/TryGhost/node-sqlite3https://raw.githubusercontent.com/TryGhost/node-sqlite3/master/test/each.test.js
- [5]raw.githubusercontent.com/TryGhost/node-sqlite3https://raw.githubusercontent.com/TryGhost/node-sqlite3/master/test/open_close.test.js
- [6]sqlite.org/loadext.htmlhttps://www.sqlite.org/loadext.html
- [7]sqlite.org/loadext.htmlhttps://www.sqlite.org/loadext.html#security_recommendations
- [8]raw.githubusercontent.com/TryGhost/node-sqlite3https://raw.githubusercontent.com/TryGhost/node-sqlite3/master/test/backup.test.js
- [9]sqlite.org/rescode.htmlhttps://www.sqlite.org/rescode.html#cantopen
- [10]github.com/TryGhost/node-sqlite3https://github.com/TryGhost/node-sqlite3/issues/796
- [11]raw.githubusercontent.com/TryGhost/node-sqlite3https://raw.githubusercontent.com/TryGhost/node-sqlite3/master/test/prepare.test.js
Need a different package?
Request a profile