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.
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
- Prompt with name ' ' already exists
- Prompt with name ' ' not found
- Resource with URI ' ' not found
- Tool with name ' ' already exists
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/9b3a5a4b86778e24.
Report an issue: GitHub.
Appendix: 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)