{"record":{"id":"5826d733b4490467","repo":"JuliusBrussee/caveman","slug":"migrate-sqlite-data-ref-q-w","errorCode":null,"errorMessage":"migrate sqlite data_ref %q: %w","messagePattern":"migrate sqlite data_ref %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/ccr/store_sqlite.go","lineNumber":225,"sourceCode":"\t\t// sidecars there would report a perfectly good database as replaced.\n\t\tmode, err := sqliteJournalMode(db)\n\t\tif err != nil {\n\t\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\t\treturn nil, fmt.Errorf(\"read sqlite journal mode: %w\", err)\n\t\t}\n\t\twalJournal = strings.EqualFold(mode, \"wal\")\n\t}\n\tif err := RetryOnBusy(func() error { _, e := db.Exec(schema); return e }); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"migrate sqlite %q: %w\", canonicalPath, err)\n\t}\n\tif err := RetryOnBusy(func() error { return ensureMetadataColumn(db) }); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"migrate sqlite metadata %q: %w\", canonicalPath, err)\n\t}\n\tif err := RetryOnBusy(func() error { return ensureDataRefColumn(db) }); err != nil {\n\t\t_ = db.Close()\n\t\treturn nil, fmt.Errorf(\"migrate sqlite data_ref %q: %w\", canonicalPath, err)\n\t}\n\tif err := configureStorageBudget(db, maxBytes); err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, fmt.Errorf(\"configure sqlite storage budget %q: %w\", canonicalPath, err)\n\t}\n\topened, err := inspectSQLiteGeneration(canonicalPath)\n\tif err != nil {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, err\n\t}\n\tif !before.sameExisting(opened) || (walJournal && (opened[1] == nil || opened[2] == nil)) {\n\t\tcloseSQLiteAfterOpenFailure(db, canonicalPath)\n\t\treturn nil, ErrStorageChanged\n\t}\n\t// The schema/budget queries have opened the WAL. Capture the resulting\n\t// journals before final permission checks, so losing a newly-created\n\t// journal is distinguishable from normal creation during SQLite open.\n\tbefore = opened","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/engine/ccr/store_sqlite.go#L207-L243","documentation":"This error wraps failure of ensureDataRefColumn, the migration step that adds the data_ref column (run inside RetryOnBusy) during store open. On failure the db is closed and open aborts. It indicates the ALTER TABLE-style migration for data_ref could not complete.","triggerScenarios":"ensureDataRefColumn's queries fail or stay SQLITE_BUSY beyond retries; database file read-only; concurrent process blocking the migration.","commonSituations":"Version upgrade from a schema predating data_ref while the db is locked by another instance; filesystem quota/permission issues preventing writes.","solutions":["Close other connections/processes to the db and retry","Verify write permission on the db file and directory","Unwrap the error chain to see the exact SQL failure and address it (e.g. disk full, corrupted page)","Restore the database from backup if the schema pages are corrupted"],"exampleFix":"// before\nsudo systemctl start app # second instance, db locked\n// after\nsystemctl stop app-old && systemctl start app # single writer only","handlingStrategy":"retry","validationCode":"if err := unix.Access(dbPath, unix.W_OK); err != nil {\n    return fmt.Errorf(\"db %s not writable for migration: %w\", dbPath, err)\n}","typeGuard":null,"tryCatchPattern":"store, err := ccr.Open(dbPath)\nif err != nil && strings.Contains(err.Error(), \"migrate sqlite data_ref\") {\n    // wait out the lock holder, then retry once\n    time.Sleep(time.Second)\n    store, err = ccr.Open(dbPath)\n}","preventionTips":["Stop all instances before schema upgrades","Verify disk quota/space on the db volume","Check file ownership matches the service user"],"tags":["sqlite","migration","alter-table"],"backgroundTag":"database-write-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}