{"record":{"id":"ad4c46c63fdf476d","repo":"tinyhumansai/openhuman","slug":"mcp-notification-method-failed-with","errorCode":null,"errorMessage":"MCP notification {method} failed with {} — {}","messagePattern":"MCP notification (.+?) failed with (.+?) — (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"src/openhuman/mcp/http_client/client.rs","lineNumber":477,"sourceCode":"    }\n\n    async fn send_notification(&self, method: &str, params: Value) -> anyhow::Result<()> {\n        let body = json!({\n            \"jsonrpc\": \"2.0\",\n            \"method\": method,\n            \"params\": params,\n        });\n        let request = self\n            .http\n            .post(&self.endpoint)\n            .header(CONTENT_TYPE, \"application/json\")\n            .header(ACCEPT, MCP_HTTP_ACCEPT);\n        let request = self.apply_standard_headers(request, false, method, None, &[]);\n        let response = request.body(serde_json::to_vec(&body)?).send().await?;\n        let status = response.status();\n        if !status.is_success() {\n            let text = response.text().await.unwrap_or_default();\n            anyhow::bail!(\n                \"MCP notification {method} failed with {} — {}\",\n                status,\n                text\n            );\n        }\n        Ok(())\n    }\n\n    async fn send_jsonrpc(\n        &self,\n        method: &str,\n        params: Value,\n        options: RequestOptions,\n    ) -> anyhow::Result<ResponseEnvelope> {\n        self.send_jsonrpc_inner(method, params, options, true).await\n    }\n\n    async fn send_jsonrpc_inner(","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/mcp/http_client/client.rs#L459-L495","documentation":"A fire-and-forget JSON-RPC notification (e.g. `notifications/initialized`) POSTed to the MCP endpoint returned a non-2xx status; the message includes the method, status and response body. Notifications carry no id and expect no reply, so any non-success HTTP status is reported this way by `send_notification`.","triggerScenarios":"Sending `notifications/initialized` or `notifications/cancelled` when the session id is stale (404), the OAuth token expired (401), or the endpoint is behind a gateway returning 4xx/5xx; servers that reject notifications for unknown sessions.","commonSituations":"Token expiring between `initialize` and the follow-up notification; server restarting and losing session state mid-handshake; misconfigured base URL pointing at a non-MCP route.","solutions":["If 401, refresh OAuth and re-initialize the session before retrying.","If 404/unknown session, re-run the full initialize handshake (new `Mcp-Session-Id`).","Verify the endpoint URL and any proxy settings; then retry once — notifications are idempotent.","If the failure is transient (5xx), back off and retry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.send_notification(method, params).await {\n    let msg = e.to_string();\n    if msg.contains(\" 401\") || msg.contains(\" 404\") {\n        client.reset_session();\n        client.initialize().await?; // then re-send once\n    } else {\n        tracing::warn!(\"mcp notification {method} failed: {e}\");\n    }\n}","preventionTips":["Send notifications as part of the same session lifecycle as initialize — never after long idle gaps.","Refresh OAuth tokens proactively before expiry windows.","Treat notification failure as non-fatal unless the handshake depends on it."],"tags":["mcp","http","notification","json-rpc"],"backgroundTag":"http-error-response","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}