alibaba/arthas · error · McpError
Resource with URI '{}' not found
Error message
Resource with URI '{}' not found What it means
Thrown by McpStatelessNettyServer.removeResource() when dynamically unregistering a resource URI not present in the stateless server's resources map. The async removal returns null from map.remove and fails the returned CompletableFuture with this McpError wrapped in CompletionException.
Source
Thrown at arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/protocol/server/McpStatelessNettyServer.java:320
}
public CompletableFuture<Void> removeResource(String resourceUri) {
if (resourceUri == null) {
CompletableFuture<Void> future = new CompletableFuture<>();
future.completeExceptionally(new McpError("Resource URI must not be null"));
return future;
}
if (this.serverCapabilities.getResources() == null) {
CompletableFuture<Void> future = new CompletableFuture<>();
future.completeExceptionally(new McpError("Server must be configured with resource capabilities"));
return future;
}
return CompletableFuture
.runAsync(() -> {
McpStatelessServerFeatures.ResourceSpecification removed = this.resources.remove(resourceUri);
if (removed == null) {
throw new CompletionException(new McpError("Resource with URI '" + resourceUri + "' not found"));
}
logger.debug("Removed resource handler: {}", resourceUri);
})
.exceptionally(ex -> {
Throwable cause = (ex instanceof CompletionException) ? ex.getCause() : ex;
logger.error("Error while removing resource '{}'", resourceUri, cause);
throw new CompletionException(cause);
});
}
private McpStatelessRequestHandler<McpSchema.ListResourcesResult> resourcesListRequestHandler() {
return (exchange, commandContext, params) -> {
List<McpSchema.Resource> resourceList = new ArrayList<>();
for (McpStatelessServerFeatures.ResourceSpecification spec : this.resources.values()) {
resourceList.add(spec.getResource());
}
return CompletableFuture.completedFuture(new McpSchema.ListResourcesResult(resourceList, null));
};View on GitHub (pinned to 21cf2e9ba5)
Solutions
- Maintain your own registry of added URIs and only remove those present.
- Make removal idempotent with exceptionally(ex -> null).
- Reuse the exact URI from registration without normalization.
- Confirm the same McpStatelessNettyServer instance owns the resource.
Example fix
// before
statelessServer.removeResource(uri).join(); // throws if absent
// after
statelessServer.removeResource(uri)
.exceptionally(ex -> null)
.join(); // idempotent Defensive patterns
Strategy: validation
Validate before calling
Set<String> addedUris = ConcurrentHashMap.newKeySet();
// on add: addedUris.add(uri);
if (addedUris.remove(resourceUri)) {
statelessServer.removeResource(resourceUri).join();
} Try / catch
statelessServer.removeResource(resourceUri)
.exceptionally(ex -> {
Throwable c = ex instanceof CompletionException ? ex.getCause() : ex;
if (c instanceof McpError me && me.getMessage().contains("not found")) return null;
throw new CompletionException(c);
})
.join(); Prevention
- Track added URIs locally.
- Make removal idempotent with exceptionally.
- Reuse the exact registered URI.
When it happens
Trigger: Calling removeResource(uri) for a URI never added, already removed, or not byte-identical to the registered key on a stateless server.
Common situations: Idempotent teardown that runs twice; cleanup of a resource that was never registered; URI normalization differences; operating on the wrong server instance.
Related errors
- Resource with URI '{}' already exists
- Resource with URI '${resourceUri}' not found
- Tool with name '{}' already exists
- Tool with name '{}' not found
- Prompt with name '{}' already exists
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/9b3a5a4b86778e24.
Report an issue: GitHub.