BigPizzaV3/CodexPlusPlus · error
unsupported sidebar catalog table
Error message
unsupported sidebar catalog table: {table} What it means
When restoring/validating the sidebar catalog from global state, each entry's 'table' field must be one of the whitelisted SIDEBAR_CATALOG_TABLES. This error is thrown for any entry naming a table outside that allowlist, preventing writes to arbitrary database tables.
Solutions
- Fix the entry's 'table' field to one of the supported catalog table names (see SIDEBAR_CATALOG_TABLES in provider_sync.rs)
- Remove the unsupported entry from the sidebar catalog section of .codex-global-state.json (or let a fresh sync rebuild it)
- Align app versions: if the state was written by a newer version, restore the matching older state or upgrade this binary
Example fix
// before
{"table": "threads_extra", "db_path": "...", "rows": []}
// after
{"table": "threads", "db_path": "...", "rows": []} Defensive patterns
Strategy: validation
Validate before calling
const TABLES: &[&str] = &["threads"]; // mirror SIDEBAR_CATALOG_TABLES
fn entry_table_ok(entry: &serde_json::Value) -> bool {
entry.get("table").and_then(Value::as_str).map(|t| TABLES.contains(&t)).unwrap_or(false)
} Type guard
fn as_known_table(v: &Value) -> Option<&str> {
v.get("table").and_then(Value::as_str).filter(|t| SIDEBAR_CATALOG_TABLES.contains(t))
} Try / catch
if let Err(e) = restore(&state) {
if e.to_string().starts_with("unsupported sidebar catalog table") {
// drop/repair the offending entry and retry
}
} Prevention
- Never hand-edit .codex-global-state.json; use app-managed sync
- Keep the writer and reader app versions aligned
- Validate table names against SIDEBAR_CATALOG_TABLES before persisting entries
When it happens
Trigger: Restoring sidebar state whose catalog entry has a 'table' value not in SIDEBAR_CATALOG_TABLES — from a hand-edited .codex-global-state.json, a newer/older schema version, or corruption.
Common situations: User edited global state JSON manually; state file written by a different app version using renamed/extra tables; migration schema drift between versions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/b17c427867c91fea.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-data/src/provider_sync.rs:2709
snapshot: &Value,
) -> anyhow::Result<()> {
let thread_id = snapshot
.get("thread_id")
.and_then(Value::as_str)
.filter(|id| !id.trim().is_empty())
.ok_or_else(|| anyhow::anyhow!("sidebar snapshot is missing thread_id"))?;
if let Some(catalog) = snapshot.get("catalog") {
let entries = catalog
.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)View on GitHub (pinned to b1ed92e5e4)