{"record":{"id":"ae02ca7c2d2894a7","repo":"BigPizzaV3/CodexPlusPlus","slug":"sidebar-catalog-entry-is-missing-db-path","errorCode":null,"errorMessage":"sidebar catalog entry is missing db_path","messagePattern":"sidebar catalog entry is missing db_path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-data/src/provider_sync.rs","lineNumber":2715,"sourceCode":"        .ok_or_else(|| anyhow::anyhow!(\"sidebar snapshot is missing thread_id\"))?;\n    if let Some(catalog) = snapshot.get(\"catalog\") {\n        let entries = catalog\n            .as_array()\n            .ok_or_else(|| anyhow::anyhow!(\"sidebar snapshot catalog must be an array\"))?;\n        let allowed_paths = sidebar_catalog_db_paths(codex_home)?;\n        for entry in entries {\n            let table = entry\n                .get(\"table\")\n                .and_then(Value::as_str)\n                .ok_or_else(|| anyhow::anyhow!(\"sidebar catalog entry is missing table\"))?;\n            if !SIDEBAR_CATALOG_TABLES.contains(&table) {\n                anyhow::bail!(\"unsupported sidebar catalog table: {table}\");\n            }\n            let path = entry\n                .get(\"db_path\")\n                .and_then(Value::as_str)\n                .map(PathBuf::from)\n                .ok_or_else(|| anyhow::anyhow!(\"sidebar catalog entry is missing db_path\"))?;\n            let canonical = fs::canonicalize(&path)?;\n            if !allowed_paths.contains(&canonical) {\n                anyhow::bail!(\"sidebar catalog database is not an allowed Codex database\");\n            }\n            let rows = entry\n                .get(\"rows\")\n                .and_then(Value::as_array)\n                .ok_or_else(|| anyhow::anyhow!(\"sidebar catalog entry rows must be an array\"))?;\n            for row in rows {\n                let row_id = row\n                    .get(\"thread_id\")\n                    .and_then(Value::as_str)\n                    .ok_or_else(|| anyhow::anyhow!(\"sidebar catalog row is missing thread_id\"))?;\n                if row_id != thread_id {\n                    anyhow::bail!(\"sidebar catalog row thread_id does not match snapshot\");\n                }\n            }\n        }","sourceCodeStart":2697,"sourceCodeEnd":2733,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-data/src/provider_sync.rs#L2697-L2733","documentation":"Each sidebar catalog entry must specify which SQLite database file it targets via a string \"db_path\" field. Without it the restore cannot locate the database and aborts. The path is later canonicalized and checked against allowed Codex databases.","triggerScenarios":"A catalog entry with no \"db_path\" key, or a non-string value (number/object/null), passed to the sidebar snapshot restore function.","commonSituations":"Hand-edited snapshot missing the path; exporter version change; entries copied between snapshots with the path stripped for privacy and not re-added; relative path stored where a resolvable path is needed.","solutions":["Add \"db_path\": \"<absolute path to the codex sqlite db>\" to the entry","Point db_path at a real Codex database under the codex home (it must canonicalize to an allowed path)","Re-export the snapshot so db_path is filled in","If the path was stripped for sharing, restore it to the local machine's actual database location"],"exampleFix":"// before\n{ \"table\": \"thread_catalog\", \"rows\": [ ... ] }\n// after\n{ \"table\": \"thread_catalog\", \"db_path\": \"/home/user/.codex/sessions.sqlite\", \"rows\": [ ... ] }","handlingStrategy":"validation","validationCode":"for (const e of snapshot.catalog ?? []) {\n  if (typeof e?.db_path !== 'string' || e.db_path.trim() === '') {\n    throw new Error('catalog entry missing db_path');\n  }\n  if (!fs.existsSync(e.db_path)) throw new Error('db_path does not exist locally');\n}","typeGuard":"function entryHasDbPath(e) {\n  return typeof e === 'object' && e !== null && typeof e.db_path === 'string' && e.db_path.trim() !== '';\n}","tryCatchPattern":"try {\n  restore_sidebar_snapshot(&snapshot, codex_home)?;\n} catch (e) {\n  if (String(e).includes('missing db_path')) {\n    rewriteDbPathsToLocalCodexHome(snapshot); // re-point entries, then retry\n  }\n}","preventionTips":["Re-export snapshots per machine instead of copying absolute paths","Resolve db_path at export time against codex_home","Strip nothing from entries when editing snapshots","Document the expected db location for shared snapshots"],"tags":["json","paths","sidebar","catalog"],"backgroundTag":"missing-required-argument","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}