Kuberwastaken/claurst · error
rmcp read_resource ' ' failed
Error message
rmcp read_resource '{}' failed: {} What it means
Raised in `RmcpClientBackend::read_resource` when the rmcp peer's `read_resource` call for the given URI fails during the `resources/read` round-trip. This wraps transport failures and JSON-RPC error responses returned by the MCP server, such as the resource not existing, the URI being malformed, or the session being closed. The URI and the underlying rmcp error are included so the failing read can be identified.
Solutions
- Re-run list_resources and confirm the URI still exists on the server before reading.
- Check the inner error text: 'not found' means stale/wrong URI; 'method not found' means no resources capability.
- Fix the URI to match exactly what the server registered (scheme, host, path).
- Reconnect the session if the transport closed, then retry.
Example fix
// before: caching URIs forever
let contents = backend.read_resource(&cached_uri).await?;
// after: refresh the resource list when a read fails
let contents = match backend.read_resource(&cached_uri).await {
Ok(c) => c,
Err(_) => {
let resources = backend.list_resources().await?;
let fresh = resources.iter().find(|r| r.name == resource_name)
.ok_or_else(|| anyhow::anyhow!("resource {resource_name} no longer exists"))?;
backend.read_resource(&fresh.uri).await?
}
}; Defensive patterns
Strategy: validation
Validate before calling
async fn ensure_resource_exists(backend: &dyn McpClientBackend, uri: &str) -> anyhow::Result<()> {
let known = backend.list_resources().await?;
anyhow::ensure!(known.iter().any(|r| r.uri == uri), "resource '{uri}' not offered by server");
Ok(())
} Try / catch
match backend.read_resource(uri).await {
Ok(c) => c,
Err(e) if e.to_string().contains("not found") => {
eprintln!("resource {uri} no longer exists; refresh resource list");
ResourceContents::default()
}
Err(e) => return Err(e),
} Prevention
- Always obtain URIs from list_resources rather than constructing them by hand.
- Refresh the resource list after server restarts; URIs are not stable across restarts.
- Match the server's exact URI scheme/template when building URIs programmatically.
- Handle 'not found' distinctly from transport errors — one is permanent, the other retryable.
When it happens
Trigger: Calling `read_resource(uri)` when the request fails at protocol level: unknown or stale URI (server returns 'resource not found'), URI not matching the server's URI template, server lacks the resources capability, transport failure, or session closed mid-call.
Common situations: Reading a resource URI discovered in a previous session after the server restarted and its resource set changed; typo in the URI scheme the server registered; reading a resource whose underlying file/database was deleted; the server requires subscription or dynamic discovery before the URI is valid.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- rmcp list_resources failed
- rmcp list_tools failed
- rmcp call_tool ' ' failed
- rmcp read_resource ' ' returned no contents
- rmcp list_prompts failed
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/87c2a97330c11f17.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/rmcp_backend.rs:543
.map_err(|e| anyhow::anyhow!("rmcp call_tool '{}' failed: {}", name, e))?;
Ok(convert_call_tool_result(result))
}
async fn list_resources(&self) -> anyhow::Result<Vec<McpResource>> {
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(View on GitHub (pinned to b0637c97ec)