Database recovery

How to recover when the embedded database is corrupted or locked.

If Roscoe can't open your database at startup, the web UI will show a recovery screen instead of the normal app. This page explains what's happening and what your options are.

What corruption looks like#

When you open Roscoe, you see a screen titled "Roscoe can't open your database" with a yellow warning icon. Below it are the path to your database file and the error message, such as database disk image is malformed.

What stays, what's lost#

  • Your workflow YAML files on disk are not affected. They live in your project folder, not in the database. The database only stores execution history.
  • Your run history is what's at risk. That's the record of which workflows ran, when, and what they produced. You can re-run a workflow to get a fresh result, but you can't recover the original outputs of a past run.

The recovery flow#

  1. The recovery screen offers one primary action: Archive & start fresh.
  2. Clicking it opens a confirmation modal that spells out exactly what stays (workflow files) and what you'll lose (run history).
  3. On confirm, Roscoe renames your current database file to roscoe.db.corrupt-<timestamp> and creates a new empty one. The original is preserved on disk. The -wal, -shm, .bak, and .restore-tmp files beside it are deleted, so any rows still held in an uncheckpointed write-ahead log are lost.
  4. The recovery screen rechecks the database and the app loads normally. There is no page reload.

The archived file lives at ~/.roscoe/roscoe.db.corrupt-<timestamp>. Keep it if you want to report the problem. Delete it once you're satisfied things are working.

Why this happens#

In rough order of likelihood:

  1. The database lives in a syncing folder (Dropbox, iCloud Drive, OneDrive, Google Drive). The sync client races SQLite for the file and corrupts it over time. To fix this permanently, move ~/.roscoe out of any synced location.
  2. Hard kill or power loss during a write. SQLite usually recovers, but not always.
  3. Disk hardware issues — bad sectors, a failing solid-state drive (SSD). If it keeps happening, the disk is worth checking.
  4. Editing the database in another tool (DB Browser for SQLite, sqlite3 CLI) and crashing the editor mid-write.

If recovery doesn't help#

If a fresh database also fails to open, something else is wrong (filesystem permissions, full disk, the wrong Bun binary). Check the terminal output where you started Roscoe for an error message. Then mail us at support@roscoe.run and include:

  • The error message from the terminal.
  • The archived file at ~/.roscoe/roscoe.db.corrupt-<timestamp>, if you still have it. We can sometimes recover the schema and rows from it.

Details#

The rest of this page is for developers reproducing the failure or reading the source. You do not need it to recover your database.

Reproducing corruption (for testing)#

Stop the server, then:

dd if=/dev/urandom of=~/.roscoe/roscoe.db bs=1024 count=10 conv=notrunc seek=2

This overwrites a chunk in the middle of the database file with random bytes. Start the server. The recovery screen should appear. Do not run this against a database with data you care about.

You can also test in isolation by overriding HOME:

TEST_HOME=$(mktemp -d)
mkdir "$TEST_HOME/.roscoe"
dd if=/dev/urandom of="$TEST_HOME/.roscoe/roscoe.db" bs=1024 count=10
HOME="$TEST_HOME" bun apps/server/src/index.ts

Then curl http://127.0.0.1:${ROSCOE_API_PORT:-8080}/api/health should return {"status":"unavailable", ...}.

Reference#

  • Server-side: apps/server/src/db-status.ts, apps/server/src/routes/admin.ts
  • DB layer: archiveAndReset() in packages/db/src/client.ts
  • Web UI: apps/web/src/components/DbRecovery/
  • Screenshot test: apps/web/e2e/db-recovery.spec.ts (baselines resolve through snapshotPathTemplate in apps/web/e2e/playwright.config.ts)

Where to next#

  • Common errors — the error-by-error index, including the 503 responses a bad database produces.
  • Global vs project stores — what lives in ~/.roscoe and what lives in your project folder.
  • REST API — the /api/health response shape the recovery screen reads.

View this page as Markdown

Predictable workflows from unpredictable AI