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

  1. Back up and delete/repair the corrupted database at the path in the message (local default from getAgentDbPath()), then re-login to repopulate credentials
  2. Run SQLite integrity repair (e.g. sqlite3 .recover / .dump to a new file) on the db before deleting it
  3. Check disk space and filesystem health to prevent recurrence
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/354059b8976f29f7. Report an issue: GitHub.