alibaba/arthas · error · McpError

Resource with URI '${resourceUri}' not found

Error message

Resource with URI '${resourceUri}' not found

What it means

Thrown by McpNettyServer.removeResource() when you try to dynamically unregister a resource whose URI is not currently registered. The server holds resources in a name-keyed map; a removal that finds no existing entry fails the returned CompletableFuture with this McpError (wrapped in a CompletionException). It is a stateful-server runtime error, distinct from the resource-capabilities-missing guard that runs before it.

Source

Thrown at arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/protocol/server/McpNettyServer.java:467

		});
	}

	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.supplyAsync(() -> {
			McpServerFeatures.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);
			return null;
		}).thenCompose(ignored -> {
			if (this.serverCapabilities.getResources().getListChanged()) {
				return notifyResourcesListChanged();
			}
			return CompletableFuture.completedFuture(null);
		}).exceptionally(ex -> {
			Throwable cause = (ex instanceof CompletionException) ? ex.getCause() : ex;
			logger.error("Error while removing resource '{}'", resourceUri, cause);
			throw new CompletionException(cause);
		});
	}

	public CompletableFuture<Void> notifyResourcesListChanged() {
		return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_RESOURCES_LIST_CHANGED, null);

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Track registered resource URIs in your own set and only call removeResource for URIs you know are present.
  2. Verify the exact URI string passed to addResource is reused verbatim for removal (no trimming/normalization).
  3. Catch CompletionException/McpError on the returned future and treat 'not found' as a no-op for idempotent cleanup.
  4. Confirm you are operating on the same McpNettyServer instance that owns the resource.

Example fix

// before
server.removeResource(uri).join(); // throws if absent

// after
Set<String> registered = ConcurrentHashMap.newKeySet();
server.addResource(spec);
registered.add(uri);
// ...
if (registered.remove(uri)) {
    server.removeResource(uri).join();
}
Defensive patterns

Strategy: validation

Validate before calling

// Track URIs you registered and guard removal
Set<String> registeredResources = ConcurrentHashMap.newKeySet();
// on add: registeredResources.add(uri);
if (registeredResources.remove(resourceUri)) {
    server.removeResource(resourceUri).join();
}

Try / catch

// Idempotent removal: swallow 'not found'
server.removeResource(resourceUri)
    .exceptionally(ex -> {
        if (isMcpError(ex, "not found")) return null;
        throw new CompletionException(ex instanceof CompletionException
            ? ex.getCause() : ex);
    })
    .join();

Prevention

When it happens

Trigger: Calling removeResource(resourceUri) where resourceUri was never added, was already removed, or has expired. Also when the URI passed does not byte-match the key used at registration (trailing slash, case, scheme).

Common situations: Double removal of the same resource; removal on a server instance that did not register the resource (e.g. wrong server or session); cleanup code running after startup registration changed order; URI normalization mismatch between add and remove.

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/7dd4bbaa8f6beb46. Report an issue: GitHub.