zeroclaw-labs/zeroclaw · error · anyhow::Error
Failed to detect Notion database schema: {e}
Error message
Failed to detect Notion database schema: {e} What it means
On startup, `listen` probes the configured Notion database to detect the status property type (`detect_status_type`); if that schema probe fails, listening aborts with this wrapped error. The inner `{e}` is almost always the `API error {status}` from the probe — invalid database ID, or a database the integration cannot see (401/403/404).
Source
Thrown at crates/zeroclaw-channels/src/notion.rs:383
.await?;
self.release_task(page_id).await;
Ok(())
}
async fn listen(&self, tx: tokio::sync::mpsc::Sender<ChannelMessage>) -> Result<()> {
// Detect status property type
match self.detect_status_type().await {
Ok(st) => {
::zeroclaw_log::record!(
INFO,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_attrs(::serde_json::json!({"st": st})),
"status property type"
);
*self.status_type.write().await = st;
}
Err(e) => {
bail!("Failed to detect Notion database schema: {e}");
}
}
// Crash recovery
if self.recover_stale
&& let Err(e) = self.recover_stale().await
{
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"error": format!("{}", e)})),
"stale task recovery failed"
);
}
// Polling loop
loop {View on GitHub (pinned to 88bb9c8533)
Solutions
- Use the raw 32-character database ID — strip the URL prefix and `?v=` query
- In Notion, open the database → ⋯ → Connections and add your integration
- Verify access before starting: `curl -H "Authorization: Bearer <api_key>" -H "Notion-Version: 2022-06-28" https://api.notion.com/v1/databases/<id>`
- Read the inner `{e}` text for the precise HTTP status
Defensive patterns
Strategy: validation
Validate before calling
let resp = client
.get(format!("https://api.notion.com/v1/databases/{database_id}"))
.header("Authorization", format!("Bearer {api_key}"))
.header("Notion-Version", "2022-06-28")
.send()
.await?;
if !resp.status().is_success() {
return Err(anyhow::anyhow!(
"notion database {database_id} not accessible: {}",
resp.status()
));
} Try / catch
match notion_channel.listen(tx).await {
Err(e) if e.to_string().contains("Failed to detect Notion database schema") => {
// inspect the inner {e}: 401/403/404 means fix database_id or integration sharing
}
other => other,
} Prevention
- Probe database accessibility with one GET before starting the listener
- Share every target database with the integration (⋯ → Connections) at setup time
- Store only the raw 32-char database ID in config and lint against URL-shaped values
When it happens
Trigger: `NotionChannel::listen` with a `database_id` that is wrong, contains URL junk (`?v=`, `Notion.so/` prefix), or refers to a database that was never shared with the integration.
Common situations: Pasting the full database URL instead of the raw ID; database duplicated/moved/deleted so the old ID is gone; integration access revoked from the database.
Related errors
- Unsupported auth profile schema version {} (max supported: {
- OpenClaw memories table found but no content-like column was
- Composio execute failed on v3 ({v3_error_summary}){prime_suf
- Composio v3 tool schema lookup failed for '{slug}': {err}
- Notion query_database failed ({status}): {truncated}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/875ebb2010ad4fb4.
Report an issue: GitHub.