{"record":{"id":"e814f371d047fab7","repo":"BigPizzaV3/CodexPlusPlus","slug":"restore-conflict-table-row-already-exists","errorCode":null,"errorMessage":"restore conflict: {table} row already exists","messagePattern":"restore conflict: (.+?) row already exists","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-data/src/storage.rs","lineNumber":1027,"sourceCode":"        }\n    }\n    Ok(())\n}\n\nfn detect_restore_conflicts(db: &Connection, tables: &Map<String, Value>) -> anyhow::Result<()> {\n    for (table, rows) in tables {\n        if table.starts_with(\"__\") {\n            continue;\n        }\n        let Some(rows) = rows.as_array() else {\n            continue;\n        };\n        for row in rows {\n            let Some(row) = row.as_object() else {\n                continue;\n            };\n            if restore_row_conflicts(db, table, row)? {\n                anyhow::bail!(\"restore conflict: {table} row already exists\");\n            }\n        }\n    }\n    Ok(())\n}\n\nfn restore_row_conflicts(\n    db: &Connection,\n    table: &str,\n    row: &Map<String, Value>,\n) -> anyhow::Result<bool> {\n    let key_columns = restore_conflict_key_columns(table, row);\n    if key_columns.is_empty() || !has_table(db, table)? {\n        return Ok(false);\n    }\n    let where_clause = key_columns\n        .iter()\n        .enumerate()","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-data/src/storage.rs#L1009-L1045","documentation":"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.","triggerScenarios":"Thrown at crates/codex-plus-data/src/storage.rs:1027 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["先删除或迁移数据库中已存在的同主键行再执行 undo","确认该 undo token 是否已被消费过（重复撤销）","使用带覆盖语义的恢复流程（如先删后恢复）","检查备份是否对应同一会话的多次删除，改用正确的那份 token"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}