Launch Offer: Use codelaunch30for 30% off

attempt to write a readonly database

This error occurs when SQLite can't write to the database file due to file permissions, the file being on a read-only filesystem, or the connection being opened in read-only mode.

The readonly database error means SQLite can write to the database file. This is usually a file system permission issue.

Understanding the Error

SQLITE_READONLY: attempt to write a readonly database

SQLite successfully opened the database but can't perform write operations (INSERT, UPDATE, DELETE, CREATE).

Common Causes

1. File Permissions

The database file or its directory doesn't allow writes:

BASH
# Check permissions
ls -la myapp.db

# Output: read-only for your user
-r--r--r--  1 root  root  12288 Jan 1 00:00 myapp.db

2. Directory Not Writable

SQLite needs to create journal files in the same directory:

BASH
# Check directory permissions
ls -la /path/to/database/

# Directory must be writable
drwxr-xr-x  2 root  root  4096 Jan 1 00:00 database/  # Not writable!

3. Read-Only Filesystem

The filesystem itself might be mounted read-only:

  • Docker containers with read-only mounts
  • Network drives
  • SD cards with write protection

4. Connection Opened Read-Only

Your code explicitly opened a read-only connection:

JAVASCRIPT
// Read-only mode
const db = new Database('myapp.db', { readonly: true });

5. Database Opened by Another Process

Another process might have an exclusive lock.

6. File Owned by Different User

Web servers often run as a different user:

BASH
# File owned by root, but web server runs as www-data
-rw-r--r--  1 root  root  12288 myapp.db

How to Fix It

Solution 1: Fix File Permissions

BASH
# Make file writable
chmod 664 myapp.db

# Or for development
chmod 666 myapp.db

Solution 2: Fix Directory Permissions

SQLite needs to write journal files:

BASH
# Make directory writable
chmod 775 /path/to/database/

# Check both file AND directory
ls -la /path/to/database/

Solution 3: Change File Ownership

Match the user running your application:

BASH
# For web servers (Apache/Nginx)
chown www-data:www-data myapp.db
chown www-data:www-data /path/to/database/

# For Node.js apps
chown nodeuser:nodeuser myapp.db

Solution 4: Check Docker Volume Mounts

YAML
# docker-compose.yml
volumes:
  # Wrong: read-only mount
  - ./data:/app/data:ro

  # Correct: read-write mount
  - ./data:/app/data:rw
  - ./data:/app/data  # rw is default

Solution 5: Use a Writable Location

Move the database to a writable directory:

JAVASCRIPT
// Instead of application directory
const db = new Database('/var/lib/myapp/data.db');

// Or user's home directory
const os = require('os');
const path = require('path');
const dbPath = path.join(os.homedir(), '.myapp', 'data.db');

Solution 6: Open in Read-Write Mode

Ensure you're not accidentally opening read-only:

JAVASCRIPT
// Explicitly read-write (default)
const db = new Database('myapp.db', { readonly: false });

// Or just
const db = new Database('myapp.db');

Solution 7: Check for WAL Files

If using WAL mode, these files also need write access:

BASH
# Check for WAL files
ls -la myapp.db*

# Output
-rw-r--r--  myapp.db
-rw-r--r--  myapp.db-shm   # Shared memory file
-rw-r--r--  myapp.db-wal   # Write-ahead log

Debugging Steps

1. Check Current Permissions

BASH
# File permissions
stat myapp.db

# Who am I running as?
whoami
id

2. Test Write Access

BASH
# Can you create a file in the directory?
touch /path/to/database/test.txt && rm /path/to/database/test.txt

3. Check Process User

BASH
# What user is the process running as?
ps aux | grep node
ps aux | grep python

4. Check Filesystem

BASH
# Is filesystem read-only?
mount | grep "path/to/database"

# Check disk space (full disk can appear read-only)
df -h /path/to/database

Platform-Specific Issues

Linux/Mac

BASH
# Fix permissions
sudo chown -R $USER:$USER /path/to/database
chmod 755 /path/to/database
chmod 644 /path/to/database/myapp.db

Docker

DOCKERFILE
# Dockerfile: ensure writable directory
RUN mkdir -p /app/data && chown -R node:node /app/data
USER node

Serverless/Lambda

JAVASCRIPT
// Use /tmp for writable storage
const dbPath = '/tmp/myapp.db';

// Copy from read-only bundle if needed
if (!fs.existsSync(dbPath)) {
  fs.copyFileSync('./myapp.db', dbPath);
}

Best Practices

  1. Store databases in data directories, not application directories
  2. Set appropriate permissions during deployment
  3. Document required permissions in your setup guide
  4. Use environment variables for database paths
  5. Test write access on application startup

Related Errors

  • SQLITE_CANTOPEN - Can't open the database file at all
  • SQLITE_BUSY - Database is locked by another connection
  • SQLITE_IOERR - General I/O error