alibaba/arthas · error · McpError

Prompt with name ' ' not found

Error message

Prompt with name '{}' not found

What it means

Thrown by McpStatelessNettyServer.removePrompt() when dynamically unregistering a prompt name not present in the stateless server's prompts map. The async removal returns null and fails the returned CompletableFuture with this McpError wrapped in CompletionException.

Solutions

  1. Track registered prompt names and remove only those present.
  2. Make teardown idempotent with exceptionally(ex -> null).
  3. Reuse the exact name string from registration.
  4. Verify you operate on the McpStatelessNettyServer that owns the prompt.

Example fix

// before
statelessServer.removePrompt(name).join(); // throws if absent

// after
statelessServer.removePrompt(name)
    .exceptionally(ex -> null)
    .join(); // idempotent cleanup
Defensive patterns

Strategy: validation

Validate before calling

Set<String> addedPrompts = ConcurrentHashMap.newKeySet();
// on add: addedPrompts.add(name);
if (addedPrompts.remove(promptName)) {
    statelessServer.removePrompt(promptName).join();
}

Try / catch

statelessServer.removePrompt(promptName)
    .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

When it happens

Trigger: Calling removePrompt(name) for a name never added, already removed, or misspelled on a stateless server.

Common situations: Double teardown; cleanup of a prompt that never registered; name mismatch; wrong server instance.

Related errors


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

Appendix: source

Thrown at arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/protocol/server/McpStatelessNettyServer.java:413

	public CompletableFuture<Void> removePrompt(String promptName) {
		if (promptName == null || promptName.isEmpty()) {
			CompletableFuture<Void> future = new CompletableFuture<>();
			future.completeExceptionally(new McpError("Prompt name must not be null or empty"));
			return future;
		}
		if (this.serverCapabilities.getPrompts() == null) {
			CompletableFuture<Void> future = new CompletableFuture<>();
			future.completeExceptionally(new McpError("Server must be configured with prompt capabilities"));
			return future;
		}

		return CompletableFuture
				.runAsync(() -> {
					McpStatelessServerFeatures.PromptSpecification removed =
							this.prompts.remove(promptName);
					if (removed == null) {
						throw new CompletionException(new McpError("Prompt with name '" + promptName + "' not found"));
					}
					logger.debug("Removed prompt handler: {}", promptName);
				})
				.exceptionally(ex -> {
					Throwable cause = (ex instanceof CompletionException) ? ex.getCause() : ex;
					logger.error("Error while removing prompt '{}'", promptName, cause);
					throw new CompletionException(cause);
				});
	}


	private McpStatelessRequestHandler<McpSchema.ListPromptsResult> promptsListRequestHandler() {
		return (exchange, commandContext, params) -> {
			List<McpSchema.Prompt> promptList = new ArrayList<>();
			for (McpStatelessServerFeatures.PromptSpecification promptSpec : this.prompts.values()) {
				promptList.add(promptSpec.getPrompt());
			}
			return CompletableFuture.completedFuture(new McpSchema.ListPromptsResult(promptList, null));

View on GitHub (pinned to 21cf2e9ba5)