can1357/oh-my-pi · error · AIError.ConfigurationError
Failed to open auth database at
Error message
Failed to open auth database at '${dbPath}' after ${maxAttempts} attempts: ${lastBusyError?.message} What it means
SqliteAuthCredentialStore opens its Bun SQLite database with a bounded retry loop for SQLITE_BUSY contention. If the database still cannot be opened after maxAttempts, it throws AIError.ConfigurationError including the db path, attempt count, and the last busy error's message (cause preserved).
Solutions
- Ensure no other process is holding the DB: close other omp/CLI sessions and retry
- Move the auth database off network/synced filesystems to local disk (check the configured dbPath)
- Check file permissions and free disk space at dbPath; delete a corrupt DB only if re-auth is acceptable
- Increase maxAttempts/baseDelayMs in environments with heavy concurrent access
Example fix
// before: auth dir on NFS AUTH_DB=~/netdrive/omp/auth.db // after: local disk AUTH_DB=~/.omp/auth.db
Defensive patterns
Strategy: retry
Validate before calling
// pre-check: can we open the DB and is it on a suitable filesystem?
const dbPath = getAuthDbPath();
const stat = await fs.stat(path.dirname(dbPath)).catch(() => null);
if (!stat) throw new Error(`auth dir missing: ${path.dirname(dbPath)}`);
if (isNetworkMount(path.dirname(dbPath))) logger.warn("auth DB on network mount; locks may time out"); Try / catch
try {
const store = new SqliteAuthCredentialStore(dbPath);
} catch (err) {
if (err instanceof AIError.ConfigurationError && err.message.includes("Failed to open auth database")) {
logger.error("Auth DB locked or unreadable", { path: dbPath, cause: err.cause });
// surface to user: close other sessions or relocate dbPath
} else throw err;
} Prevention
- Keep the auth database on local disk, not NFS/SMB/synced folders
- Avoid running many concurrent CLI sessions against the same auth DB
- Monitor disk space and file permissions on the auth directory
- Treat this error as environmental: check for lock holders before retrying
When it happens
Trigger: The auth DB file is locked for longer than the retry window — another omp process holds a write lock, an antivirus/indexer has the file open, the DB lives on a network filesystem, or the file is corrupt so SQLite fails immediately on every attempt.
Common situations: Running multiple CLI sessions/workers that refresh auth concurrently; the auth directory on NFS/SMB/Dropbox-synced storage; stale lock from a crashed process; disk-full or permission issues surfacing as repeated open failures.
Related errors
- No credential with id=
- WAL checkpoint failed for
- Aborted before execution
- ACP session fork is unavailable while a prompt is in…
- Agent is already processing. Use steer() or followUp() to…
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/98ce044ad138bd43.
Report an issue: GitHub.
Appendix: source
Thrown at packages/ai/src/auth/sqlite-credential-store.ts:557
try {
await fs.chmod(dbPath, 0o600);
} catch {
// Ignore chmod failures (e.g., Windows)
}
SqliteAuthCredentialStore.#ensureAuthCredentialRefreshLeasesTable(db);
return new SqliteAuthCredentialStore(db);
} catch (err) {
db?.close();
if (!isSqliteBusyError(err)) {
throw err;
}
lastBusyError = err instanceof Error ? err : new Error(String(err));
if (attempt < maxAttempts - 1) {
await Bun.sleep(baseDelayMs * 2 ** attempt);
}
}
}
throw new AIError.ConfigurationError(
`Failed to open auth database at '${dbPath}' after ${maxAttempts} attempts: ${lastBusyError?.message}`,
{ cause: lastBusyError },
);
}
static #ensureAuthCredentialRefreshLeasesTable(db: Database): void {
db.run(`
CREATE TABLE IF NOT EXISTS auth_credential_refresh_leases (
credential_id INTEGER PRIMARY KEY,
owner TEXT NOT NULL,
expires_at_ms INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_auth_credential_refresh_leases_expires ON auth_credential_refresh_leases(expires_at_ms);
`);
}
/**View on GitHub (pinned to 9690622007)