Kuberwastaken/claurst · warning

rmcp read_resource ' ' returned no contents

Error message

rmcp read_resource '{}' returned no contents

What it means

Raised in `RmcpClientBackend::read_resource` after a SUCCESSFUL `resources/read` round-trip: the server returned a result whose `contents` array is empty, and since this backend returns a single `ResourceContents`, `.into_iter().next()` finds nothing and this explicit error is thrown. Unlike error 196 this is not a transport/protocol failure — the server answered, but had no content for the URI. The URI is embedded in the message.

Solutions

  1. Treat empty-contents as a legitimate outcome: match on this error and return an empty/default value instead of failing.
  2. Verify on the server side whether the resource backing data is empty or generation failed.
  3. If the resource should have content, check the server logs for errors in its resource provider.
  4. Prefer checking the resource's metadata (size/mime) from list_resources before reading.

Example fix

// before: any read failure aborts the pipeline
let contents = backend.read_resource(uri).await?;
// after: accept empty resources as empty content
let contents = match backend.read_resource(uri).await {
    Ok(c) => c,
    Err(e) if e.to_string().ends_with("returned no contents") => ResourceContents::empty(),
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: try-catch

Try / catch

match backend.read_resource(uri).await {
    Ok(contents) => contents,
    Err(e) if e.to_string().ends_with("returned no contents") => {
        tracing::info!(uri, "resource has no content; using empty default");
        ResourceContents::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `read_resource(uri)` for a resource the server knows about but that currently has no content: an empty file backing the resource, a resource whose generation failed server-side, a legitimately empty resource (empty log, empty query result), or a server bug returning `contents: []` instead of an error.

Common situations: Reading an empty text file exposed as an MCP resource; reading a resource computed on demand where the underlying source returned nothing; MCP servers that model 'not found yet' as an empty contents list rather than a JSON-RPC error; pipelines that assume every listed resource has at least one content part.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/dbc2e26bd73a1ae2. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:548

        let resources = self
            .peer
            .list_all_resources()
            .await
            .map_err(|e| anyhow::anyhow!("rmcp list_resources failed: {}", e))?;
        Ok(resources.into_iter().map(convert_resource).collect())
    }

    async fn read_resource(&self, uri: &str) -> anyhow::Result<ResourceContents> {
        let result = self
            .peer
            .read_resource(rmcp_model::ReadResourceRequestParams::new(uri.to_string()))
            .await
            .map_err(|e| anyhow::anyhow!("rmcp read_resource '{}' failed: {}", uri, e))?;
        let first = result
            .contents
            .into_iter()
            .next()
            .ok_or_else(|| anyhow::anyhow!("rmcp read_resource '{}' returned no contents", uri))?;
        Ok(convert_resource_contents(first))
    }

    async fn list_prompts(&self) -> anyhow::Result<Vec<McpPrompt>> {
        let prompts = self
            .peer
            .list_all_prompts()
            .await
            .map_err(|e| anyhow::anyhow!("rmcp list_prompts failed: {}", e))?;
        Ok(prompts.into_iter().map(convert_prompt).collect())
    }

    async fn get_prompt(
        &self,
        name: &str,
        arguments: Option<HashMap<String, String>>,
    ) -> anyhow::Result<GetPromptResult> {
        let mut params = rmcp_model::GetPromptRequestParams::new(name.to_string());

View on GitHub (pinned to b0637c97ec)