BigPizzaV3/CodexPlusPlus · error · anyhow::Error
restore conflict: {table} row already exists
Error message
restore conflict: {table} row already exists What it means
Thrown by detect_restore_conflicts during undo when a row carried by the backup already exists in the target table (matching conflict key). Restores deliberately never overwrite live data, so the pre-flight conflict scan bails naming the table; the offending input is the existing {table} row that collides with the backup's row.
Source
Thrown at crates/codex-plus-data/src/storage.rs:1027
}
}
Ok(())
}
fn detect_restore_conflicts(db: &Connection, tables: &Map<String, Value>) -> anyhow::Result<()> {
for (table, rows) in tables {
if table.starts_with("__") {
continue;
}
let Some(rows) = rows.as_array() else {
continue;
};
for row in rows {
let Some(row) = row.as_object() else {
continue;
};
if restore_row_conflicts(db, table, row)? {
anyhow::bail!("restore conflict: {table} row already exists");
}
}
}
Ok(())
}
fn restore_row_conflicts(
db: &Connection,
table: &str,
row: &Map<String, Value>,
) -> anyhow::Result<bool> {
let key_columns = restore_conflict_key_columns(table, row);
if key_columns.is_empty() || !has_table(db, table)? {
return Ok(false);
}
let where_clause = key_columns
.iter()
.enumerate()View on GitHub (pinned to f2074595a2)
Solutions
- 先删除或迁移数据库中已存在的同主键行再执行 undo
- 确认该 undo token 是否已被消费过(重复撤销)
- 使用带覆盖语义的恢复流程(如先删后恢复)
- 检查备份是否对应同一会话的多次删除,改用正确的那份 token
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/codex-plus-data/src/storage.rs:1027 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@f2074595a2 (2026-08-23).
Data as JSON: /api/errors/e814f371d047fab7.
Report an issue: GitHub.