GitoxideLabs/gitoxide · error
Cannot handle database with version
Error message
Cannot handle database with version {version}, cannot yet migrate to {VERSION} - maybe migrate by hand? What it means
When `gitoxide_core::corpus::db::create` opens a corpus database whose `meta.version` exists and differs from the supported `VERSION`, it closes the connection and aborts with this bail! message. The corpus schema has no migration machinery, so mismatched versions are refused rather than migrated, and the user is told to migrate manually.
Solutions
- Delete or archive the old corpus database and let `create` build a fresh one with the current version.
- Migrate the database by hand (adjust the `meta.version` row and schema) to match the expected VERSION.
- Pin the gitoxide version that matches the existing database.
- Inspect the current version with a SQL query: `SELECT version FROM meta;` and compare with the expected constant.
Example fix
// before
match version {
Some(version) if version != VERSION => match con.close() {
Ok(()) => bail!("Cannot handle database with version {version}, cannot yet migrate to {VERSION} - maybe migrate by hand?"),
Err((_, err)) => return Err(err.into()),
},
_ => {}
}
// after
match version {
None => { con.execute("INSERT into meta(version) values(?)", params![VERSION])?; }
Some(v) if v != VERSION => { migrations::apply(&mut con, v, VERSION)?; }
_ => {}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Check the corpus DB version before opening with the new tool
let version: Option<u32> = rusqlite::Connection::open(db_path)?
.query_row("SELECT version FROM meta", [], |r| r.get(0))
.ok();
if let Some(v) = version {
if v != EXPECTED_VERSION { eprintln!("corpus DB version {v} unsupported - migrate or recreate"); }
} Try / catch
match gitoxide_core::corpus::db::create(&db_path) {
Ok(db) => { /* proceed */ }
Err(err) if err.to_string().contains("cannot yet migrate") => {
// archive old DB and recreate
std::fs::rename(db_path, db_path.with_extension("old"))?;
let db = gitoxide_core::corpus::db::create(&db_path)?;
}
Err(err) => return Err(err.into()),
} Prevention
- Check the `meta.version` row before reusing an existing corpus DB with a new gitoxide build.
- Treat corpus databases as version-specific artifacts; recreate them after upgrading gitoxide.
- Record the gitoxide version alongside benchmark/corpus artifacts so mismatches are obvious.
- If you must keep data, export it before migrating, since the tool migrates nothing automatically.
When it happens
Trigger: Opening/creating a corpus database file created by a different gitoxide-core version whose stored schema version does not match the compiled-in `VERSION` constant.
Common situations: Upgrading or downgrading gitoxide and reusing an old corpus database from a benchmark/revision-collection run.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/194131be72330016.
Report an issue: GitHub.
Appendix: source
Thrown at gitoxide-core/src/corpus/db.rs:68
/// A version to be incremented whenever the database layout is changed, to refresh it automatically.
const VERSION: usize = 1;
pub fn create(path: impl AsRef<std::path::Path>) -> anyhow::Result<rusqlite::Connection> {
let path = path.as_ref();
let con = rusqlite::Connection::open(path)?;
let meta_table = r#"
CREATE TABLE if not exists meta(
version int
)"#;
con.execute_batch(meta_table)?;
let version: Option<usize> = con.query_row("SELECT version FROM meta", [], |r| r.get(0)).optional()?;
match version {
None => {
con.execute("INSERT into meta(version) values(?)", params![VERSION])?;
}
Some(version) if version != VERSION => match con.close() {
Ok(()) => {
bail!(
"Cannot handle database with version {version}, cannot yet migrate to {VERSION} - maybe migrate by hand?"
);
}
Err((_, err)) => return Err(err.into()),
},
_ => {}
}
con.execute_batch("PRAGMA synchronous = OFF; PRAGMA journal_mode = WAL; PRAGMA wal_checkpoint(FULL); ")?;
con.execute_batch(
r#"
CREATE TABLE if not exists runner(
id integer PRIMARY KEY,
vendor text,
brand text,
host_name text, -- this is just to help ID the runner
UNIQUE (vendor, brand)
)
"#,View on GitHub (pinned to e73179060b)