gastownhall/beads · error
legacy SQLite schema drift in %s hidden column
Error message
legacy SQLite schema drift in %s hidden column
What it means
verifyTable reads PRAGMA table_xinfo for each table and rejects any column whose 'hidden' flag is non-zero. Non-zero hidden values indicate generated, virtual, or internal (e.g. STRICT/virtual-table shadow) columns that are not part of the audited legacy layout — evidence the table shape deviates from the exact contract this package migrates. The error names the offending table.
Source
Thrown at internal/migration/legacysqlite/reader.go:343
}
func verifyTable(ctx context.Context, db *sql.Tx, table, want string) error {
rows, err := db.QueryContext(ctx, "PRAGMA table_xinfo("+table+")")
if err != nil {
return err
}
defer rows.Close()
var got []string
for rows.Next() {
var cid, hidden int
var name, typ string
var notNull, pk int
var defaultValue sql.NullString
if err := rows.Scan(&cid, &name, &typ, ¬Null, &defaultValue, &pk, &hidden); err != nil {
return err
}
if hidden != 0 {
return fmt.Errorf("legacy SQLite schema drift in %s hidden column", table)
}
defaultText := "-"
if defaultValue.Valid {
defaultText = defaultValue.String
}
got = append(got, fmt.Sprintf("%s|%s|%d|%s|%d", name, typ, notNull, defaultText, pk))
}
if err := rows.Err(); err != nil {
return err
}
if strings.Join(got, " ") != want {
return fmt.Errorf("legacy SQLite schema drift in %s", table)
}
return nil
}
func verifyFKs(ctx context.Context, db *sql.Tx, table string) error {
rows, err := db.QueryContext(ctx, "PRAGMA foreign_key_list("+table+")")View on GitHub (pinned to 71377f2769)
Solutions
- Compare the table definition: sqlite3 beads.db ".schema issues" and remove/revert generated or virtual columns so the layout matches the documented legacy schema
- Restore the original database from a backup taken before the schema was modified
- Recreate the table with the canonical legacy schema and copy rows into it, then retry the export
- Check with the bd project which release produced the file; an unexpected producer may have introduced drift
Example fix
-- inspect for generated columns sqlite3 beads.db "PRAGMA table_xinfo(issues);" -- last column (hidden) must be 0 for every row -- fix: rebuild the table without the generated column sqlite3 beads.db "CREATE TABLE issues_new (...same legacy columns...); INSERT INTO issues_new SELECT <cols> FROM issues; DROP TABLE issues; ALTER TABLE issues_new RENAME TO issues;"
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: ensure no hidden/generated columns in any legacy table
func checkNoHiddenColumns(dbPath string, tables []string) error {
db, err := sql.Open("sqlite3", dbPath+"?mode=ro"); if err != nil { return err }
defer db.Close()
for _, t := range tables {
rows, err := db.Query("PRAGMA table_xinfo(" + t + ")"); if err != nil { return err }
for rows.Next() {
var cid, hidden int; var name, typ string; var nn, pk int; var d sql.NullString
if err := rows.Scan(&cid, &name, &typ, &nn, &d, &pk, &hidden); err != nil { rows.Close(); return err }
if hidden != 0 { rows.Close(); return fmt.Errorf("%s: hidden column %s", t, name) }
}
rows.Close()
}
return nil
} Try / catch
if err := legacysqlite.Export(ctx, src, out, os.Stdout); err != nil {
if strings.Contains(err.Error(), "hidden column") {
return fmt.Errorf("database has generated/virtual columns; restore original schema or rebuild the table before export")
}
return err
} Prevention
- Never add generated or virtual columns to legacy databases you intend to migrate
- Only let the supported bd release create/modify the schema
- Keep a pre-modification backup of the legacy database
- Audit .schema output against the documented legacy layout before migrating
When it happens
Trigger: Export -> read -> verify -> verifyTable: a row from PRAGMA table_xinfo(<table>) has hidden != 0 for any of metadata, issues, dependencies, labels, comments. Occurs when the table was created as a virtual table, has generated columns, or was modified by tooling.
Common situations: The database was produced or altered by a different tool or schema generator that added generated columns; a virtual-table-based shim replaced a real table; custom patches to the legacy schema.
Related errors
- legacy SQLite schema drift in %s
- legacy SQLite release marker: %w
- legacy SQLite issue %s uses unsupported removed fields
- clone from %s succeeded, but the database needs %d schema %s
- sealed legacy SQLite database does not match source fingerpr
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/dbf572dc9ad54716.
Report an issue: GitHub.