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

  1. Use the raw 32-character database ID — strip the URL prefix and `?v=` query
  2. In Notion, open the database → ⋯ → Connections and add your integration
  3. Verify access before starting: `curl -H "Authorization: Bearer <api_key>" -H "Notion-Version: 2022-06-28" https://api.notion.com/v1/databases/<id>`
  4. 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

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


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/875ebb2010ad4fb4. Report an issue: GitHub.