[BUG] SQLite writes fail on connected-folder mount (disk I/O error / database is locked); failed writes leave stray journal/lock artifacts

Status Open
Maintainer reply None cached
Activity 0 comments · opened Sep 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Running normal SQLite3 write operations (INSERT, CREATE TABLE IF NOT EXISTS, commit) against a .db file that lives inside a Cowork connected folder fails consistently with sqlite3.OperationalError: disk I/O error.

This happens whether the write is issued from device_bash (running locally on the user's own machine, per its tool description) or from the cloud-container Bash tool — same failure either way, so it appears tied to the connected-folder mount itself, not the local/cloud split.

Switching the connection to SQLite's unix-dotfile locking mode (file:path?vfs=unix-dotfile) lets reads succeed, but writes still fail — either the same disk I/O error on insert/commit, or "database is locked" on a subsequent PRAGMA call.

Worse, a failed write is not a clean no-op: it left a stray rollback-journal file (<db>-journal) and a stray lock artifact (<db>.lock, created as a directory under unix-dotfile mode) sitting next to the live database. In one reproduction a partially-committed write also left a stray table behind in the actual database file. None of this could be cleaned up until the session explicitly called device_request_delete_permission and the user approved deletion for the whole connected folder — i.e., recovering from a failed write required an extra permission grant just to remove debris the platform's own failed operation created.

This looks like it may share a root cause with #55206 (bash sandbox can create files on a mounted host folder but unlink is denied, breaking git's lock-file cleanup) — that issue documents the mount denying unlink() until delete permission is granted, which matches why the stray SQLite journal/lock files couldn't be removed. But the SQLite case also shows a distinct failure — disk I/O error during an active write/commit, before any cleanup is attempted — which looks like the mount not honoring POSIX advisory (fcntl) locking, not just denying unlink.

What Should Happen?

Either: (1) SQLite reads and writes against a file inside a connected folder should work the same as a genuinely local path — the mount should transparently support the locking/journaling primitives SQLite needs; or (2) if the mount technology can't support that, a write should fail atomically and cleanly, with no orphaned -journal or .lock files/directories and no partially-committed tables, so recovering never requires a delete-permission round-trip.

Error Messages/Logs

sqlite3.OperationalError: disk I/O error

(raised from either conn.execute(...) or conn.commit(), depending on when SQLite needs to touch its journal file)

With vfs=unix-dotfile:
sqlite3.OperationalError: disk I/O error
sqlite3.OperationalError: database is locked

Steps to Reproduce

  1. Connect a folder to a Cowork session that contains (or will contain) a SQLite3 .db file.
  2. 2. From device_bash, cd into the mounted folder (e.g. $HOME/mnt/<folder-name>) and run:
  3. ```python
  4. import sqlite3
  5. conn = sqlite3.connect("some_file.db")
  6. conn.execute("INSERT INTO some_table (...) VALUES (...)")
  7. conn.commit()
  8. ```
  9. 3. Observe: sqlite3.OperationalError: disk I/O error (can occur on the execute or the commit).
  10. 4. Retry using the unix-dotfile VFS:
  11. ```python
  12. sqlite3.connect("file:some_file.db?vfs=unix-dotfile", uri=True)
  13. ```
  14. Reads succeed; writes still fail with disk I/O error or database is locked.
  15. 5. ls the folder afterward — a stray <db>-journal file and/or <db>.lock directory remain next to the real .db file.
  16. 6. Copy the same .db file to a path outside the mount (e.g. the device_bash VM's own home directory, not under $HOME/mnt/...) and repeat step 2 there — it succeeds every time. Copying the result back over the mounted path with a plain cp also succeeds every time.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

N/A — Cowork desktop app session (not the Claude Code CLI)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

Note: this happened inside Claude (Cowork) with a connected local folder — via the mcp__remote-devices__* device bridge / device_bash, not the Claude Code CLI in a real terminal. That's why the CLI-specific fields above don't cleanly apply.

Environment: Claude (Cowork), session linked to a local Mac via the Claude desktop app (connected folder / device bridge feature). Connected folder mounted into the session at $HOME/mnt/<folder-name>. Target file: a small (~12-16 KB) SQLite3 database, accessed via Python's stdlib sqlite3 module. Reproduced identically via device_bash (runs locally on the user's machine) and the cloud-container Bash tool.

Possibly related: #55206 (same connected-folder mount denying unlink(), observed via git lock files instead of SQLite).

View original on GitHub ↗