can1357/oh-my-pi · critical · Error
Persistent credential block store ${store} is unavailable af
Error message
Persistent credential block store ${store} is unavailable after SQLite corruption What it means
AuthStorage latches #persistedBlockStoreDamaged when the persisted credential block store (SQLite-backed) hits unrecoverable corruption. Once latched, #assertPersistedBlockStoreWritable throws this Error on any operation requiring the persisted store, with the store location so the operator can repair or replace it. The library refuses to write credentials into a known-corrupt store rather than risk data loss.
Source
Thrown at packages/ai/src/auth-storage.ts:1941
credentialId,
provider,
providerKey,
blockScope,
blockedUntilMs: nextBlockedUntil,
});
}
}
#handlePersistedBlockStoreError(err: unknown): boolean {
if (!isSqliteCorruptionError(err)) return false;
this.#reportDamagedBlockStore(err);
return true;
}
#assertPersistedBlockStoreWritable(): void {
if (!this.#persistedBlockStoreDamaged) return;
const store = this.#sourceLabel ?? `local ${getAgentDbPath()}`;
throw new Error(`Persistent credential block store ${store} is unavailable after SQLite corruption`);
}
/**
* Latches {@link AuthStorage.#persistedBlockStoreDamaged} on the first
* unrecoverable persisted-block store error and surfaces it once at `error`
* level with the store location, so an operator can repair or replace it.
* Later reads/writes short-circuit silently — the in-memory backoff map keeps
* rate-limit blocks applying for the life of the process; only cross-process
* persistence is lost.
*/
#reportDamagedBlockStore(err: unknown): void {
if (this.#persistedBlockStoreDamaged) return;
this.#persistedBlockStoreDamaged = true;
const store = this.#sourceLabel ?? `local ${getAgentDbPath()}`;
logger.error(
"Persistent credential store is corrupt; cross-process rate-limit persistence is disabled for this process. In-memory backoff still applies. Repair the store with `sqlite3 <path> '.recover'` or delete it to recreate on next login.",
{ err, store },
);View on GitHub (pinned to 9690622007)
Solutions
- Back up and delete/repair the corrupted database at the path in the message (local default from getAgentDbPath()), then re-login to repopulate credentials
- Run SQLite integrity repair (e.g. sqlite3 .recover / .dump to a new file) on the db before deleting it
- Check disk space and filesystem health to prevent recurrence
- If #sourceLabel names a remote store, repair or replace that store, then restart the process
Example fix
// before await storage.storeCredential(credential); // throws: store damaged // after // mv ~/.omp/agent.db ~/.omp/agent.db.corrupt (or run sqlite3 .recover) // restart process, re-run OAuth logins await storage.storeCredential(credential);
Defensive patterns
Strategy: try-catch
Try / catch
try {
await storage.storeCredential(credential);
} catch (error) {
if (String(error).includes("unavailable after SQLite corruption")) {
quarantineDbAndAlert(); // back up the corrupt db, notify operator
}
throw error;
} Prevention
- Monitor disk space and fsync-safe storage for the agent db path
- Never copy or truncate the SQLite file while the app is running
- Back up the credential db periodically so recovery is cheap
- Alert on the latched damage log line so repair happens before writes are needed
When it happens
Trigger: Any AuthStorage operation that must read/write persisted credential blocks after an earlier SQLite error latched the damage flag (e.g. storing, listing, or blocking credentials), when the underlying SQLite database at getAgentDbPath() (or a remote #sourceLabel store) is corrupt.
Common situations: Disk full/crash mid-write corrupting the agent SQLite db; file copied while the app was running; incompatible/older SQLite file format after version downgrade; permission issues manifesting as persistent store errors.
Related errors
- Invalid security store scan index at ${this.#indexPath()}
- entry name contains NUL
- Failed to open auth database at '${dbPath}' after ${maxAttem
- Cleanse session could not be persisted
- WAL checkpoint failed for ${dbPath}: busy=${result.busy}, wa
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/354059b8976f29f7.
Report an issue: GitHub.