How to fix Sequelize ConnectionError: SQLITE_CANTOPEN in SQLite

SQLiteBEGINNERHIGHUpdated Dec 29, 2025· 145 views

This error occurs when Sequelize cannot open the SQLite database file at the specified path. Common causes include missing database file, incorrect file path, missing parent directory, or insufficient file/directory permissions. The error prevents Sequelize from establishing a connection to your SQLite database.

Quick fix

Fixes SQLITE_CANTOPEN

const path = require('path');
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: path.join(__dirname, 'database.sqlite')  // Absolute path
  // NOT: storage: 'database.sqlite'               // Avoid relative paths
});
  1. Use an absolute file path instead of relative path
  2. Ensure the parent directory exists
  3. Fix file permissions on database and directory
  4. Check disk space and temp directory
sqlite — error
const path = require('path');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: path.join(__dirname, 'database.sqlite') // Absolute path
// NOT: storage: 'database.sqlite' // Avoid relative paths
});
Sequelize ConnectionError: SQLITE_CANTOPEN

What this error means

The SQLITE_CANTOPEN error indicates that SQLite's underlying file system layer cannot open the database file. When using Sequelize with SQLite, this error is wrapped in a "ConnectionError" and prevents your application from connecting to the database. This typically happens when: - The database file does not exist at the specified path - The parent directory does not exist - The application lacks read or write permissions to the database file or directory - The file path is incorrectly specified (relative vs absolute paths, Windows drive letter issues) - The database is locked or in use by another process - The directory where the database should be created lacks write permissions Unlike other databases (PostgreSQL, MySQL), SQLite is file-based, so any filesystem-level issue directly prevents connection.

Typical symptoms

  • Sequelize connection fails immediately with "SequelizeConnectionError: SQLITE_CANTOPEN"
  • Application crashes on startup when initializing Sequelize
  • Error mentions "unable to open database file"
  • Works on Linux/Mac but fails on Windows (or vice versa)
  • Permissions error occurs when running with restricted user
  • Docker/container environment reports SQLITE_CANTOPEN on volume mounts

Common causes

  1. Database file path does not exist and parent directory is missing
  2. Incorrect relative path causing Sequelize to look in wrong directory
  3. Insufficient permissions on database file or parent directory
  4. Database directory is not writable by the application user
  5. Using relative path without understanding working directory context
  6. Windows drive letter issues when specifying cross-drive paths
  7. Database locked or corrupted from previous crash
  8. Disk full or quota exceeded preventing file creation
  9. Temporary directory (used by SQLite for WAL/journal files) is not writable

How to fix "Sequelize ConnectionError: SQLITE_CANTOPEN"

1Use an absolute file path instead of relative path

Relative paths can be confusing in Node.js. Always use absolute paths with Sequelize SQLite. Update your connection configuration:

javascript
const path = require('path');
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: path.join(__dirname, 'database.sqlite')  // Absolute path
  // NOT: storage: 'database.sqlite'               // Avoid relative paths
});

Or with environment variables:

bash
.env
DATABASE_PATH=/var/lib/myapp/database.sqlite
javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: process.env.DATABASE_PATH || path.join(__dirname, 'database.sqlite')
});

The key is using path.join(__dirname, ...) or an explicit absolute path, not a relative path string.

2Ensure the parent directory exists

SQLite cannot create the database file if its parent directory doesn't exist. Create the directory before initializing Sequelize:

javascript
const fs = require('fs');
const path = require('path');

const dbDir = path.dirname(process.env.DATABASE_PATH || './data/database.sqlite');
if (!fs.existsSync(dbDir)) {
  fs.mkdirSync(dbDir, { recursive: true });
}

const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: process.env.DATABASE_PATH || './data/database.sqlite'
});

The { recursive: true } option creates all parent directories if they don't exist.

3Fix file permissions on database and directory

Ensure the application user has read/write permissions to both the database file and its parent directory:

bash
# Make directory writable by application user
chmod 755 /path/to/database/directory

# If file exists, ensure it's readable and writable
chmod 644 /path/to/database/database.sqlite

# In Docker, use the correct user
chown -R appuser:appuser /path/to/database/

# Verify permissions are correct
ls -la /path/to/database/

In Docker containers, ensure your Dockerfile doesn't run as root and that volume mounts have correct permissions:

dockerfile
# Create app user (not root)
RUN useradd -m -u 1000 appuser

# Set proper permissions before user switch
RUN mkdir -p /app/data && chown -R appuser:appuser /app/data

# Switch to non-root user
USER appuser

WORKDIR /app
COPY . .
4Check disk space and temp directory

SQLite needs to write temporary files (WAL files, journal files) in the same directory as the database. Check available disk space and temp directory permissions:

bash
# Check disk space
df -h /path/to/database/

# Check temp directory exists and is writable
ls -la /tmp
ls -la $TMPDIR

# On macOS, TMPDIR might be set to a custom location
echo $TMPDIR

If the disk is full or temp directory is missing:

javascript
// Configure SQLite to use a specific temp directory
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: '/path/to/database.sqlite',
  dialectOptions: {
    timeout: 60000  // Increase timeout if I/O is slow
  }
});

// Or set the environment variable
process.env.SQLITE_TMPDIR = '/tmp';
5Handle in-memory databases correctly

If using in-memory SQLite (useful for testing), ensure the configuration is correct:

javascript
// Correct way to use in-memory database
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: ':memory:'  // Not a file path
});

// NOT: storage: 'sqlite://:memory:'  // This will fail

// For persistent in-memory during session
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: ':memory:',
  logging: console.log  // Enable logging for debugging
});

However, :memory: databases are lost when your application restarts. For testing with persistence, use a temporary file instead:

javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: path.join(os.tmpdir(), 'test-db.sqlite')
});
6Add comprehensive error handling and logging

Enable detailed logging to understand exactly what path Sequelize is trying to use:

javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: process.env.DATABASE_PATH || './database.sqlite',
  logging: (msg) => console.log('[SQL]', msg),  // Log all SQL
  dialectOptions: {
    timeout: 30000
  }
});

// Log database connection details
sequelize.authenticate()
  .then(() => {
    console.log('Database connection successful');
    console.log('Database path:', sequelize.options.storage);
  })
  .catch((err) => {
    console.error('Database connection failed:');
    console.error('Error:', err.message);
    console.error('Expected path:', sequelize.options.storage);

    // Check if path exists
    const fs = require('fs');
    const path = require('path');
    const dbPath = sequelize.options.storage;
    const dirExists = fs.existsSync(path.dirname(dbPath));
    const fileExists = fs.existsSync(dbPath);

    console.error('Parent directory exists:', dirExists);
    console.error('Database file exists:', fileExists);
  });

The logging output will show you the exact path Sequelize is trying to use.

7Test with a simple standalone SQLite script

Before debugging Sequelize, test SQLite directly to isolate the issue:

javascript
const sqlite3 = require('sqlite3');
const path = require('path');

const dbPath = path.join(__dirname, 'test.sqlite');

const db = new sqlite3.Database(dbPath, (err) => {
  if (err) {
    console.error('SQLite connection failed:');
    console.error('Error:', err.message);
    console.error('Code:', err.code);
    console.error('Path:', dbPath);
  } else {
    console.log('SQLite connected successfully');

    db.serialize(() => {
      db.run('CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT)');
      db.run('INSERT INTO test (name) VALUES (?)', ['Hello']);

      db.all('SELECT * FROM test', (err, rows) => {
        if (err) console.error('Query error:', err);
        else console.log('Rows:', rows);
        db.close();
      });
    });
  }
});

If this works but Sequelize fails, the issue is in your Sequelize configuration, not SQLite itself.

Advanced notes

WAL Mode and Temporary Files:

When using SQLite with WAL (Write-Ahead Logging) enabled, SQLite creates additional files:
- database.sqlite-wal: Write-ahead log
- database.sqlite-shm: Shared memory file

These files must be in the same directory as the main database file, and the directory must be writable. If the directory is read-only (common in some deployment scenarios), enable read-only mode:

javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: '/readonly/path/database.sqlite',
  dialectOptions: {
    mode: 1  // SQLITE_OPEN_READONLY
  }
});

Platform-Specific Issues:

Windows: Avoid using backslashes in paths. Use path.join() or forward slashes:

javascript
// Good
const dbPath = path.join(__dirname, 'db', 'database.sqlite');
const dbPath = 'C:/Users/user/db/database.sqlite';

// Bad
const dbPath = 'C:\\Users\\user\\db\\database.sqlite';  // Escaping issues

Docker: Use volume mounts with explicit ownership:

bash
docker run -v /host/path:/container/path:rw myapp

macOS: Ensure TMPDIR is properly set:

bash
# Check current TMPDIR
echo $TMPDIR

# If unset or problematic, set explicitly
export TMPDIR=/var/tmp

Lock Files and Concurrent Access:

If multiple processes access the same SQLite database simultaneously, lock timeouts can occur. Increase the timeout:

javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: './database.sqlite',
  dialectOptions: {
    timeout: 60000  // 60 seconds, default is 5000
  }
});

Connection Pooling:

SQLite doesn't use traditional connection pools, but Sequelize can manage connection lifecycle:

javascript
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: './database.sqlite',
  pool: {
    max: 1,      // SQLite works best with single connection
    min: 0,
    acquire: 30000,
    idle: 10000
  }
});

Frequently asked questions

What does "SQLITE_CANTOPEN" mean?
The SQLITE_CANTOPEN error indicates that SQLite's underlying file system layer cannot open the database file. When using Sequelize with SQLite, this error is wrapped in a "ConnectionError" and prevents your application from connecting to the database. This typically happens when: - The database file does not exist at the specified path - The parent directory does not exist - The application lacks read or write permissions to the database file or directory - The file path is incorrectly specified (relative vs absolute paths, Windows drive letter issues) - The database is locked or in use by another process - The directory where the database should be created lacks write permissions Unlike other databases (PostgreSQL, MySQL), SQLite is file-based, so any filesystem-level issue directly prevents connection.
How do I fix "SQLITE_CANTOPEN"?
This error occurs when Sequelize cannot open the SQLite database file at the specified path. Common causes include missing database file, incorrect file path, missing parent directory, or insufficient file/directory permissions. The error prevents Sequelize from establishing a connection to your SQLite database.
What causes "SQLITE_CANTOPEN"?
Database file path does not exist and parent directory is missing Incorrect relative path causing Sequelize to look in wrong directory Insufficient permissions on database file or parent directory
Is the "SQLITE_CANTOPEN" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading