SQLite: unable to open database file (tested)

sqlite3.OperationalError: unable to open database file fires when sqlite3 can't even create or open the file handle itself — a step earlier than a permission problem on an existing file. We reproduced two distinct causes and measured where the error actually happens.

1. The parent directory doesn't exist

We pointed connect() at a path inside a directory that was never created:

con = sqlite3.connect("/tmp/sq_uo/nonexistentdir/x.db")
con.execute("CREATE TABLE t(id INTEGER)")
sqlite3.OperationalError: unable to open database file

Unlike a missing database file (which connect() creates silently — see our no such table guide), a missing parent directory is not created for you, and fails immediately on the first real operation.

2. The parent directory exists but can't be written to

We made a directory and removed its write permission, then pointed at a new (not-yet-existing) file inside it:

$ chmod 555 /tmp/sq_uo/rodir
con = sqlite3.connect("/tmp/sq_uo/rodir/new.db")
con.execute("CREATE TABLE t(id INTEGER)")
sqlite3.OperationalError: unable to open database file

Measured: this gives the identical error text to the missing-directory case — the message doesn't tell you which of the two it is. It's also a different error from attempt to write a readonly database: that one fires when the file already exists and SQLite can open it but not write to it; this one fires earlier, when SQLite can't even create the file handle in the first place.

3. The fix: check the directory, not just the path string

Since the error text is identical for both causes, check the parent directory directly instead of guessing from the message:

import os
d = os.path.dirname(os.path.abspath(db_path))
print(os.path.isdir(d), os.access(d, os.W_OK))

False for the first means create the directory; False for the second means fix its permissions (chmod u+w). We confirmed both independently resolve the error with no other change.

Frequently asked questions

What's the difference between 'unable to open database file' and 'attempt to write a readonly database'?

We measured both: 'unable to open' fires when SQLite can't create or open the file handle at all (missing parent directory, or no permission to create a new file there). 'Readonly database' fires later, when the file already exists and opens fine but can't be written to.

Does sqlite3.connect() create missing parent directories for me?

No — we confirmed it creates a missing database file, but not a missing parent directory. Pointing at a path inside a directory that doesn't exist yet fails immediately with 'unable to open database file' on the first real operation.

How do I tell which of the two causes I'm hitting?

The error text is identical for both in our test, so check directly: os.path.isdir() on the parent directory tells you if it's missing, and os.access(dir, os.W_OK) tells you if it exists but isn't writable.

Does this happen with in-memory databases (:memory:)?

Not applicable — :memory: databases have no file path at all, so this error, which we reproduced specifically against real file paths with missing or unwritable parent directories, doesn't apply to them.

Is this the same error as a locked database?

No — we measured 'database is locked' separately: that happens when the file opens fine but another connection already holds a write lock. 'Unable to open' happens before any lock is ever involved, at the file-handle-creation step.

Written with AI assistance. Measured on 2026-10-03 with Python 3.13.5's built-in sqlite3 module, connecting to a path whose parent directory doesn't exist and, separately, a new file inside a read-only directory. Every error string below is copy-pasted output, not paraphrased. PlainHeaders is our extension; Python's sqlite3 is built in.