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

  1. Verify the name refers to a real table, not an internal index — query `SELECT name, type, sql FROM sqlite_master WHERE name = ?` yourself
  2. Inspect the table's columns via PRAGMA table_info instead of the CREATE statement
  3. 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

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


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