Hi, When SQLite fails to create a file it tries reopening readonly and only if that fails too it logs the error. However by that time the original error (for file creation) is lost.
Testcase: $ cat >testcase.sh <<END mkdir /tmp/foo && sqlite3 /tmp/foo/x.db <<EOF pragma journal_mode=wal; create table x(x int); EOF chmod -w /tmp/foo gcc sqlite3.c testcase.c -ldl -DSQLITE_THREADSAFE=0 -o testcase strace -e open ./testcase /tmp/foo/x.db END $ cat >testcase.c <<EOF #include <sqlite3.h> #include <stdio.h> static void qlog(void *parg, int errcode, const char *msg) { fprintf(stderr,"SQLite error %x: %s\n", errcode, msg); } int main(int argc, char *argv[]) { const char *path = argv[1]; sqlite3 *handle = NULL; int ret = 0; char *errmsg = NULL; if (argc != 2) { fprintf(stderr,"Usage: %s </path/to/db>\n", argv[0]); return 1; } sqlite3_config(SQLITE_CONFIG_LOG, qlog, NULL); if (sqlite3_open_v2(path, &handle, SQLITE_OPEN_READWRITE, NULL)) { fprintf(stderr, "Failed to open database: %s\n", sqlite3_errmsg(handle)); ret = 2; } else if (sqlite3_exec(handle, "PRAGMA synchronous = NORMAL", NULL, NULL, &errmsg)) { fprintf(stderr, "exec failed: %s\n", errmsg); sqlite3_free(errmsg); ret = 3; } sqlite3_close(handle); return ret; } EOF $ sh testcase.sh wal open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 open("/tmp/foo/x.db", O_RDWR|O_CLOEXEC) = 3 open("/tmp/foo/x.db-wal", O_RDWR|O_CREAT|O_CLOEXEC, 0644) = -1 EACCES (Permission denied) open("/tmp/foo/x.db-wal", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) SQLite error e: cannot open file at line 30945 of [f73337e3e2] SQLite error e: os_unix.c:30945: (2) open(/tmp/foo/x.db-wal) - No such file or directory SQLite error e: unable to open database file exec failed: unable to open database file +++ exited with 3 +++ Would it be possible to save the errno when 1st robust_open fails, and report both errno when the 2nd open fails here? fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; fd = robust_open(zName, openFlags, openMode); } if( fd<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); goto open_finished; } Best regards, --Edwin