{"record":{"id":"08934f2b0b5b8b58","repo":"zeroclaw-labs/zeroclaw","slug":"notion-create-page-failed-status-truncated","errorCode":null,"errorMessage":"Notion create_page failed ({status}): {truncated}","messagePattern":"Notion create_page failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/notion_tool.rs","lineNumber":126,"sourceCode":"        let url = format!(\"{NOTION_API_BASE}/pages\");\n        let mut body = json!({ \"properties\": properties });\n        if let Some(db_id) = database_id {\n            body[\"parent\"] = json!({ \"database_id\": db_id });\n        }\n        let resp = self\n            .http\n            .post(&url)\n            .headers(self.headers()?)\n            .json(&body)\n            .timeout(std::time::Duration::from_secs(NOTION_REQUEST_TIMEOUT_SECS))\n            .send()\n            .await?;\n        let status = resp.status();\n        if !status.is_success() {\n            let text = resp.text().await.unwrap_or_default();\n            let truncated =\n                crate::util_helpers::truncate_with_ellipsis(&text, MAX_ERROR_BODY_CHARS);\n            anyhow::bail!(\"Notion create_page failed ({status}): {truncated}\");\n        }\n        resp.json().await.map_err(Into::into)\n    }\n\n    /// Update an existing Notion page's properties.\n    async fn update_page(\n        &self,\n        page_id: &str,\n        properties: &serde_json::Value,\n    ) -> anyhow::Result<serde_json::Value> {\n        let url = format!(\"{NOTION_API_BASE}/pages/{page_id}\");\n        let body = json!({ \"properties\": properties });\n        let resp = self\n            .http\n            .patch(&url)\n            .headers(self.headers()?)\n            .json(&body)\n            .timeout(std::time::Duration::from_secs(NOTION_REQUEST_TIMEOUT_SECS))","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/notion_tool.rs#L108-L144","documentation":"The Notion tool's create_page action sent POST https://api.notion.com/v1/pages and Notion rejected it with a non-2xx status; the message includes the status and truncated response body explaining why the page could not be created.","triggerScenarios":"Parent database or page not shared with the integration (404); properties payload that does not match the parent database's schema, e.g. sending a title value for a property defined as a number (400 validation_error); missing required title property; invalid parent object; bad token (401/403).","commonSituations":"Automations that create rows from templates break when the database schema changes (a property renamed or retyped) while the payload was hardcoded. Also: creating a page under a parent page that the integration cannot see, and copy-pasted payloads from a different database.","solutions":["Inspect the status and body excerpt: 400 validation_error usually names the offending property","Read the parent database first and build the properties payload from its actual property names and types","For 404, share the parent database/page with the integration before creating under it","Confirm the title property is included and typed as title/rich_text as the schema requires","For auth failures, rotate and reconfigure the integration token"],"exampleFix":"// before (property 'Priority' is a number in the database)\n{\"action\":\"create_page\",\"parent\":{\"database_id\":\"<id>\"},\"properties\":{\"Priority\":{\"rich_text\":[{\"text\":{\"content\":\"high\"}}]}}}\n// after\n{\"action\":\"create_page\",\"parent\":{\"database_id\":\"<id>\"},\"properties\":{\"Priority\":{\"number\":1}}}","handlingStrategy":"validation","validationCode":"// Build properties from the live schema: read the database, map each property\ntype, then emit\nfn coerce_value(prop_type: &str, raw: &str) -> serde_json::Value {\n    match prop_type {\n        \"number\" => json!({\"number\": raw.parse::<f64>().unwrap_or(0.0) }),\n        \"select\" => json!({\"select\": {\"name\": raw } }),\n        _ => json!({\"rich_text\": [{\"text\": {\"content\": raw }}]}),\n    }\n}","typeGuard":null,"tryCatchPattern":"Err(e) if e.to_string().contains(\"create_page failed (400)\") => {\n    // re-read parent schema, rebuild payload once, then fail loudly if still 400\n}","preventionTips":["Never hardcode property payloads; generate them from the database schema at run time","Prefer creating pages under parents the integration already reads successfully","Add a canary create+archive call in deployment checks to catch schema drift early"],"tags":["notion","http","api","page","create","rust"],"backgroundTag":"notion-api-error","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}