BigPizzaV3/CodexPlusPlus · error
sidebar catalog database is not an allowed Codex database
Error message
sidebar catalog database is not an allowed Codex database
What it means
Each sidebar catalog entry's db_path, after canonicalization, must be present in the allowlist of Codex database paths. This error blocks restore operations against any SQLite file that is not a recognized Codex database, guarding against arbitrary-file overwrites.
Solutions
- Set db_path to the actual Codex sessions database location for this machine (let the app re-derive it or fix the JSON)
- Remove symlinks in the path so canonicalize() yields the expected directory, or update the allowlist source to include the new canonical location
- If the state came from another machine, re-sync sidebar state locally instead of restoring the foreign db_path
Example fix
// before
{"table":"threads","db_path":"C:\\old\\sessions\\state.db"}
// after
{"table":"threads","db_path":"C:\\Users\\me\\.codex\\sessions\\state.db"} Defensive patterns
Strategy: validation
Validate before calling
let canonical = std::fs::canonicalize(&db_path)?;
if !allowed_paths.contains(&canonical) {
eprintln!("db_path {} is not an allowed Codex database", canonical.display());
} Type guard
fn allowed_db(p: &Path, allowed: &[PathBuf]) -> bool {
p.canonicalize().map(|c| allowed.contains(&c)).unwrap_or(false)
} Try / catch
if let Err(e) = restore(&state) {
if e.to_string().contains("not an allowed Codex database") {
// re-derive db_path locally and rewrite the entry before retrying
}
} Prevention
- Derive db_path from the app's own session-dir resolution, not from foreign state files
- Avoid symlinks inside the sessions path so canonicalization is predictable
- Re-sync state per machine instead of copying global state across hosts
When it happens
Trigger: Restoring sidebar state where an entry's 'db_path' canonicalizes to a path not in allowed_paths (external DB, symlinked path, moved session storage, or path spelled differently from the canonical form).
Common situations: User relocated the Codex sessions directory; db_path contains a symlink or relative path resolving elsewhere; state file copied between machines with different user homes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- 仅支持 Codex++ 分享站点链接
- refusing to delete script outside user script directory
- API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段
- API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段
- Base URL 不得指向本机或私有网络
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/7281ecdd08441d59.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-data/src/provider_sync.rs:2718
.as_array()
.ok_or_else(|| anyhow::anyhow!("sidebar snapshot catalog must be an array"))?;
let allowed_paths = sidebar_catalog_db_paths(codex_home)?;
for entry in entries {
let table = entry
.get("table")
.and_then(Value::as_str)
.ok_or_else(|| anyhow::anyhow!("sidebar catalog entry is missing table"))?;
if !SIDEBAR_CATALOG_TABLES.contains(&table) {
anyhow::bail!("unsupported sidebar catalog table: {table}");
}
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(())
}View on GitHub (pinned to b1ed92e5e4)