tinyhumansai/openhuman · warning · anyhow::Error

MCP DELETE failed with {}

Error message

MCP DELETE failed with {}

What it means

`close_session` sends `DELETE` to the MCP endpoint with the stored `Mcp-Session-Id`; any status other than success or 405 Method Not Allowed bails with this message. 405 is explicitly tolerated because servers are not required to implement session deletion — so this error means the server understood the DELETE and rejected it (e.g. 404 unknown session, 401 expired token), not that it merely lacks the endpoint.

Source

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

        }
        parse_sse_events(&text)
    }

    pub async fn close_session(&self) -> anyhow::Result<()> {
        let session_id = self.state.lock().session_id.clone();
        let Some(session_id) = session_id else {
            return Ok(());
        };
        let response = self
            .http
            .delete(&self.endpoint)
            .header(HEADER_SESSION_ID, session_id)
            .send()
            .await?;
        if !(response.status().is_success()
            || response.status() == reqwest::StatusCode::METHOD_NOT_ALLOWED)
        {
            anyhow::bail!("MCP DELETE failed with {}", response.status());
        }
        let mut state = self.state.lock();
        state.initialized = false;
        state.session_id = None;
        state.initialize = None;
        state.cached_tools.clear();
        Ok(())
    }

    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)

View on GitHub (pinned to 7491200858)

Solutions

  1. Treat close-session failure as best-effort: log and continue — servers expire sessions on their own anyway.
  2. On 401, refresh the token first if you need a clean close; otherwise skip.
  3. On 5xx from a proxy, retry once with backoff or ignore.

Example fix

// before
client.close_session().await?;

// after — teardown is best-effort
if let Err(e) = client.close_session().await {
    tracing::debug!("mcp session close best-effort failed: {e}");
}
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = client.close_session().await {
    tracing::debug!("best-effort session close failed: {e}"); // never fail teardown on this
}

Prevention

When it happens

Trigger: Closing a session whose id the server already expired/evicted (404); closing with an expired or revoked OAuth token (401); gateway errors (502/503) at teardown time.

Common situations: Cleanup at app shutdown racing the server's own session GC; teardown after the SSE stream already broke; load-balanced deployments where the DELETE lands on a node that never held the session.

Related errors


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