can1357/oh-my-pi · error · ToolError
SQLite schema for table '${table}' is unavailable
Error message
SQLite schema for table '${table}' is unavailable What it means
getTableSchema reads the CREATE statement from sqlite_master via getTableMasterRow and throws when the stored `sql` column is null/empty. SQLite stores NULL in sqlite_master.sql for certain internal or implicitly created objects (e.g. auto-indexes), so no schema text exists to return.
Source
Thrown at packages/coding-agent/src/tools/sqlite-reader.ts:688
)
.all();
const estimates = loadRowEstimates(db);
return names.map(({ name }) => {
const estimate = estimates.get(name);
// Trust the planner only when it says the table is too large to count
// cheaply; otherwise count exactly (bounded), which also corrects a
// stale-low estimate without ever scanning more than `cap` rows.
const count: TableRowCount =
estimate !== undefined && estimate > cap ? { kind: "estimate", rows: estimate } : probeRowCount(db, name, cap);
return { name, count };
});
}
export function getTableSchema(db: Database, table: string): string {
const row = getTableMasterRow(db, table);
if (!row.sql) {
throw new ToolError(`SQLite schema for table '${table}' is unavailable`);
}
return row.sql;
}
export function getTablePrimaryKey(db: Database, table: string): { column: string; type: string } | null {
const primaryKeyColumns = getPrimaryKeyColumns(db, table);
if (primaryKeyColumns.length !== 1) {
return null;
}
const column = primaryKeyColumns[0]!;
return { column: column.name, type: column.type };
}
export function resolveTableRowLookup(db: Database, table: string): SqliteRowLookup {
const primaryKeyColumns = getPrimaryKeyColumns(db, table);
if (primaryKeyColumns.length === 1) {
const column = primaryKeyColumns[0]!;View on GitHub (pinned to 9690622007)
Solutions
- Verify the name refers to a real table, not an internal index — query `SELECT name, type, sql FROM sqlite_master WHERE name = ?` yourself
- Inspect the table's columns via PRAGMA table_info instead of the CREATE statement
- If it's a UNIQUE-constraint auto-index, the constraint is visible in the schema of the parent table
Example fix
// before
const schema = getTableSchema(db, "sqlite_autoindex_users_1");
// after
const row = db.query("SELECT type, sql FROM sqlite_master WHERE name = ?").get("sqlite_autoindex_users_1");
if (!row?.sql) console.log("internal object; check parent table schema instead"); Defensive patterns
Strategy: try-catch
Validate before calling
const row = db.query("SELECT type, sql FROM sqlite_master WHERE name = ? AND type = 'table'").get(tableName);
if (!row || typeof row.sql !== "string" || row.sql.length === 0) {
// skip schema display; use PRAGMA table_info(tableName) instead
} Type guard
function hasSchemaText(row: { sql: string | null } | undefined): row is { sql: string } {
return typeof row?.sql === "string" && row.sql.length > 0;
} Try / catch
try {
const schema = getTableSchema(db, table);
} catch (err) {
if (err instanceof ToolError && err.message.includes("is unavailable")) {
const cols = db.query(`PRAGMA table_info(${quoteSqliteIdentifier(table)})`).all();
// synthesize schema from column info
} else throw err;
} Prevention
- Only request schema for user tables (name NOT LIKE 'sqlite_%'), not internal/auto-index objects
- Check sqlite_master.type === 'table' before fetching the CREATE statement
- Fall back to PRAGMA table_info for objects without stored SQL
When it happens
Trigger: Calling getTableSchema on a table whose sqlite_master row has sql IS NULL — typically an internal object like an implicit index (`sqlite_autoindex_*`) or a shadow/legacy object that getTableMasterRow matched but which was never created by explicit SQL.
Common situations: Enumerating all schema objects and hitting auto-indexes created by UNIQUE constraints; requesting a schema for a virtual-table shadow table; a corrupted or partially migrated database.
Related errors
- SQLite table '${table}' has no column named '${column}'
- SQLite table '${table}' has a composite primary key; use '?w
- SQLite table '${table}' does not expose ROWID; use '?where='
- Failed to open auth database at '${dbPath}' after ${maxAttem
- Persistent credential block store ${store} is unavailable af
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/aabe101226caf678.
Report an issue: GitHub.