{"record":{"id":"c8243a7915d9fa8c","repo":"juanfont/headscale","slug":"running-migration-202501311657-w","errorCode":null,"errorMessage":"running migration 202501311657: %w","messagePattern":"running migration 202501311657: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"hscontrol/db/db.go","lineNumber":1175,"sourceCode":"\t)\n}\n\nfunc runMigrations(cfg types.DatabaseConfig, dbConn *gorm.DB, migrations *gormigrate.Gormigrate) error {\n\tif cfg.Type == types.DatabaseSqlite {\n\t\t// SQLite: Run the early migrations that GORM cannot handle safely with\n\t\t// foreign keys enabled (route and pre-auth-key automigrations) with FK\n\t\t// disabled, then run everything else with FK enabled.\n\t\t//\n\t\t// NO NEW MIGRATIONS SHOULD RUN WITH FK DISABLED. As of 2025-07-02, all\n\t\t// new migrations must run with foreign keys enabled via the\n\t\t// migrations.Migrate() call below.\n\t\tif err := dbConn.Exec(\"PRAGMA foreign_keys = OFF\").Error; err != nil { //nolint:noinlineerr\n\t\t\treturn fmt.Errorf(\"disabling foreign keys: %w\", err)\n\t\t}\n\n\t\t// Run up to and including the last migration that requires FK disabled.\n\t\tif err := migrations.MigrateTo(\"202501311657\"); err != nil { //nolint:noinlineerr\n\t\t\treturn fmt.Errorf(\"running migration 202501311657: %w\", err)\n\t\t}\n\n\t\tif err := dbConn.Exec(\"PRAGMA foreign_keys = ON\").Error; err != nil { //nolint:noinlineerr\n\t\t\treturn fmt.Errorf(\"restoring foreign keys: %w\", err)\n\t\t}\n\n\t\t// Run the rest of the migrations\n\t\tif err := migrations.Migrate(); err != nil { //nolint:noinlineerr\n\t\t\treturn err\n\t\t}\n\n\t\t// Check for constraint violations at the end\n\t\ttype constraintViolation struct {\n\t\t\tTable           string\n\t\t\tRowID           int\n\t\t\tParent          string\n\t\t\tConstraintIndex int\n\t\t}","sourceCodeStart":1157,"sourceCodeEnd":1193,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/db/db.go#L1157-L1193","documentation":"On sqlite, headscale first migrates up to and including migration '202501311657' with foreign keys disabled — the last migration permitted to run FK-off (the set is frozen as of 2025-07-02). This error means one of those early migrations failed during MigrateTo.","triggerScenarios":"An existing database whose early schema disagrees with the migration scripts (schema_migrations records a version but the tables were altered), or a lock/corruption issue during the early phase. Also fires on fresh DBs if InitSchema's AutoMigrate step fails.","commonSituations":"Database restored from a partial backup; schema edited by external tooling; sqlite file truncated. Distinct from later-migration failures (error 400/401 path) because these run with FKs off.","solutions":["Read the chained gormigrate error to identify the failing early migration.","Validate the sqlite file: sqlite3 headscale.db 'PRAGMA integrity_check;'.","Restore from a known-good backup or litestream replica if integrity fails.","For a fresh start, move the DB file aside and let headscale recreate it, then re-register nodes."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Pre-migration integrity check for sqlite:\n// sqlite3 headscale.db 'PRAGMA integrity_check;'   # expect: ok\n// sqlite3 headscale.db 'SELECT * FROM schema_migrations;' # inspect version state","typeGuard":null,"tryCatchPattern":"// On failure, fall back to the most recent backup/replica:\n// restore, verify integrity, restart headscale. Do not hand-edit\n// schema_migrations to 'skip' a migration.","preventionTips":["Maintain continuous backups (litestream for sqlite, pg_dump schedules for postgres).","Test upgrades on a copy of production data first.","Avoid interrupting headscale during startup/migration windows."],"tags":["database","sqlite","migration","foreign-keys"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}