juanfont/headscale · critical
checking if table %s exists: %w
Error message
checking if table %s exists: %w
What it means
The SQLite schema-recreation migration failed querying sqlite_master to test whether a table (users, pre_auth_keys, api_keys, nodes, policies) exists before renaming it. A bare SELECT from sqlite_master failing indicates a broken connection, corrupted database file, or a non-SQLite database reaching SQLite-only code.
Source
Thrown at hscontrol/db/db.go:293
"idx_users_deleted_at",
"idx_provider_identifier",
"idx_name_provider_identifier",
"idx_name_no_provider_identifier",
"idx_api_keys_prefix",
"idx_policies_deleted_at",
}
for _, index := range indexesToDrop {
_ = tx.Exec("DROP INDEX IF EXISTS " + index).Error
}
for _, table := range tablesToRename {
// Check if table exists before renaming
var exists bool
err := tx.Raw("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?", table).Row().Scan(&exists)
if err != nil {
return fmt.Errorf("checking if table %s exists: %w", table, err)
}
if exists {
// Drop old table if it exists from previous failed migration
_ = tx.Exec("DROP TABLE IF EXISTS " + table + "_old").Error
// Rename current table to _old
err := tx.Exec("ALTER TABLE " + table + " RENAME TO " + table + "_old").Error
if err != nil {
return fmt.Errorf("renaming table %s to %s_old: %w", table, table, err)
}
}
}
// Create new tables with correct schema
tableCreationSQL := []string{
`CREATE TABLE users(
id integer PRIMARY KEY AUTOINCREMENT,View on GitHub (pinned to 565fd254d0)
Solutions
- Run 'sqlite3 headscale.db "PRAGMA integrity_check;"' to detect corruption.
- If corrupt, restore from backup - do not continue migrating a damaged file.
- Verify the database configuration (type, path) matches the actual file.
- If healthy, retry with exclusive access and check dmesg/logs for disk errors.
Defensive patterns
Strategy: try-catch
Validate before calling
-- Run before upgrading: confirm the file is a healthy SQLite database PRAGMA integrity_check; -- expect: ok
Try / catch
if _, err := db.NewHeadscaleDatabase(cfg); err != nil {
if strings.Contains(err.Error(), "checking if table") {
// sqlite_master unreadable: corruption or wrong db.type config - restore backup
}
} Prevention
- Run PRAGMA integrity_check on the SQLite file before major upgrades.
- Ensure cfg db.type matches the actual database backend.
- Use clean shutdowns (SIGTERM, not SIGKILL) to avoid corrupting the SQLite file.
When it happens
Trigger: The Raw('SELECT COUNT(*) FROM sqlite_master ...').Row().Scan fails due to a dropped connection, a corrupted SQLite file (run PRAGMA integrity_check), or a misconfigured database type where the SQLite migration runs against another backend.
Common situations: Database file corrupted by power loss or forced kill during an earlier write; headscale.cfg pointing db.type to sqlite while the file is actually a Postgres dump or vice versa; disk errors.
Related errors
- automigrating types.Route: %w
- adding prefix column: %w
- clearing expiry on tagged nodes: %w
- foreign key constraints violated
- version check: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/209f9733a89aff26.
Report an issue: GitHub.