tinyhumansai/openhuman · warning · anyhow::Error

MCP notification {method} failed with {} — {}

Error message

MCP notification {method} failed with {} — {}

What it means

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`.

Source

Thrown at src/openhuman/mcp/http_client/client.rs:477

    }

    async fn send_notification(&self, method: &str, params: Value) -> anyhow::Result<()> {
        let body = json!({
            "jsonrpc": "2.0",
            "method": method,
            "params": params,
        });
        let request = self
            .http
            .post(&self.endpoint)
            .header(CONTENT_TYPE, "application/json")
            .header(ACCEPT, MCP_HTTP_ACCEPT);
        let request = self.apply_standard_headers(request, false, method, None, &[]);
        let response = request.body(serde_json::to_vec(&body)?).send().await?;
        let status = response.status();
        if !status.is_success() {
            let text = response.text().await.unwrap_or_default();
            anyhow::bail!(
                "MCP notification {method} failed with {} — {}",
                status,
                text
            );
        }
        Ok(())
    }

    async fn send_jsonrpc(
        &self,
        method: &str,
        params: Value,
        options: RequestOptions,
    ) -> anyhow::Result<ResponseEnvelope> {
        self.send_jsonrpc_inner(method, params, options, true).await
    }

    async fn send_jsonrpc_inner(

View on GitHub (pinned to 7491200858)

Solutions

  1. If 401, refresh OAuth and re-initialize the session before retrying.
  2. If 404/unknown session, re-run the full initialize handshake (new `Mcp-Session-Id`).
  3. Verify the endpoint URL and any proxy settings; then retry once — notifications are idempotent.
  4. If the failure is transient (5xx), back off and retry.
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = client.send_notification(method, params).await {
    let msg = e.to_string();
    if msg.contains(" 401") || msg.contains(" 404") {
        client.reset_session();
        client.initialize().await?; // then re-send once
    } else {
        tracing::warn!("mcp notification {method} failed: {e}");
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/ad4c46c63fdf476d. Report an issue: GitHub.