BigPizzaV3/CodexPlusPlus · error
sidebar catalog row is missing thread_id
Error message
sidebar catalog row is missing thread_id
What it means
Every row in a sidebar catalog entry must carry a string "thread_id" so the restore can verify the row belongs to the snapshot's thread. A row without the field aborts the restore. This prevents injecting rows for unrelated threads through a snapshot.
Solutions
- Add "thread_id": "<same id as snapshot thread_id>" to each row object
- Ensure every row's thread_id matches the snapshot's top-level thread_id exactly (see also the mismatch error)
- Re-export the snapshot so rows are complete
- Drop rows that are missing thread_id instead of restoring partial data
Example fix
// before
{ "title": "My thread", "updated_at": 123 }
// after
{ "thread_id": "3f9c...", "title": "My thread", "updated_at": 123 } Defensive patterns
Strategy: validation
Validate before calling
const tid = snapshot.thread_id;
for (const e of snapshot.catalog ?? []) {
for (const row of e.rows ?? []) {
if (typeof row?.thread_id !== 'string' || row.thread_id !== tid) {
throw new Error('row thread_id missing or mismatched');
}
}
} Type guard
function rowHasThreadId(row, tid) {
return typeof row?.thread_id === 'string' && row.thread_id === tid;
} Try / catch
try {
restore_sidebar_snapshot(&snapshot, codex_home)?;
} catch (e) {
if (String(e).includes('row is missing thread_id')) {
dropOrRepairRowsWithoutThreadId(snapshot);
}
} Prevention
- Filter rows by the snapshot's thread_id at export time
- Never copy rows between snapshots of different threads
- Validate every row against the snapshot thread_id before restore
- Reject partial row objects instead of restoring incomplete data
When it happens
Trigger: A row object inside entry["rows"] that has no "thread_id" key or whose value is not a string, passed to the sidebar snapshot restore function.
Common situations: Rows copied from another snapshot or table without their thread_id; hand-edited rows; partial row objects assembled manually; exporter version with differently shaped rows.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- sidebar catalog entry is missing db_path
- sidebar catalog entry is missing table
- sidebar catalog entry rows must be an array
- sidebar snapshot is missing thread_id
- 整理结果包含无效来源
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/ad254400d703f58a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-data/src/provider_sync.rs:2728
}
let path = entry
.get("db_path")
.and_then(Value::as_str)
.map(PathBuf::from)
.ok_or_else(|| anyhow::anyhow!("sidebar catalog entry is missing db_path"))?;
let canonical = fs::canonicalize(&path)?;
if !allowed_paths.contains(&canonical) {
anyhow::bail!("sidebar catalog database is not an allowed Codex database");
}
let rows = entry
.get("rows")
.and_then(Value::as_array)
.ok_or_else(|| anyhow::anyhow!("sidebar catalog entry rows must be an array"))?;
for row in rows {
let row_id = row
.get("thread_id")
.and_then(Value::as_str)
.ok_or_else(|| anyhow::anyhow!("sidebar catalog row is missing thread_id"))?;
if row_id != thread_id {
anyhow::bail!("sidebar catalog row thread_id does not match snapshot");
}
}
}
}
Ok(())
}
const SIDEBAR_CATALOG_TABLES: [&str; 3] = [
"local_thread_catalog",
"thread_timeline_ledger",
"local_thread_catalog_scan_entries",
];
fn snapshot_thread_from_global_state(
codex_home: &Path,
thread_id: &str,View on GitHub (pinned to b1ed92e5e4)