Files
Gregory SchierandClaude Opus 5 c9e884d4fe fix(models): return a database error instead of panicking when the pool is exhausted
Two users on 2026.7.x reported the app going half-dead: local editing kept
working, but Send did nothing and every encrypted secret rendered blank until
they restarted. The webview console carried a Rust task panic —

    Delete task failed: task 1314 panicked with message
    "Failed to get new DB connection from the pool: Error(None)"

`Error(None)` is r2d2's acquire timeout. `QueryManager::connect` and `with_tx`
turned that timeout into `expect`, so a pool that was momentarily full took down
whatever task asked for a connection instead of reporting a failure the caller
could show, retry, or ignore. Every DB-backed path shares those two functions,
which is why one stalled pool reads as "Send is dead and the secrets are gone".

Acquisition is now fallible end to end: `connect()` and `BlobManager::connect()`
return `Result`, and so do the `db()`/`blobs()` accessors on every host. Call
sites propagate with `?` where they already returned a result; the fire-and-forget
writers (streaming events, the model-change poller) log and carry on. `with_conn`
had no callers and only added a third panic, so it is gone.

Two places held a pooled connection across work that has nothing to do with the
database and can block for a long time — the OS keyring in
`EncryptionManager::get_workspace_key`, and the sync directory walk in
`cmd_sync_calculate`. Both now hand the connection back first. Those are the
paths behind the two visible symptoms.

Not fixed here: the gRPC streaming block in yaak-app-client still `.unwrap()`s
its database writes, as it did before, so acquisition failures panic there too.
`ProxyQueryManager` in the separate proxy app keeps its own `expect`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 17:09:02 -07:00
..