alibaba/arthas · error · McpError

Prompt with name ' ' already exists

Error message

Prompt with name '{}' already exists

What it means

Thrown by McpStatelessNettyServer.addPrompt() when dynamically registering a PromptSpecification whose prompt name already exists in the stateless server's prompts map (putIfAbsent returns non-null). The async add fails the returned CompletableFuture with this McpError wrapped in CompletionException.

Solutions

  1. removePrompt first (idempotently) to upsert, or check current prompts before adding.
  2. Use unique namespaced prompt names.
  3. Catch CompletionException/McpError and skip on duplicate.
  4. Coordinate prompt registration to prevent concurrent duplicate adds.

Example fix

// before
statelessServer.addPrompt(spec).join(); // name exists

// after
String name = spec.getPrompt().getName();
statelessServer.removePrompt(name).exceptionally(ex -> null).join();
statelessServer.addPrompt(spec).join();
Defensive patterns

Strategy: validation

Validate before calling

String name = spec.getPrompt().getName();
statelessServer.removePrompt(name).exceptionally(ex -> null).join();
statelessServer.addPrompt(spec).join();

Try / catch

try {
    statelessServer.addPrompt(spec).join();
} catch (CompletionException e) {
    Throwable c = e.getCause();
    if (c instanceof McpError me && me.getMessage().contains("already exists")) {
        statelessServer.removePrompt(spec.getPrompt().getName())
            .exceptionally(x -> null).join();
        statelessServer.addPrompt(spec).join();
    } else throw e;
}

Prevention

When it happens

Trigger: Calling addPrompt(spec) at runtime when getPrompt().getName() collides with an existing prompt; re-adding after a successful add.

Common situations: Live prompt re-registration; plugin load colliding with an existing prompt name; retry-based double add.

Related errors


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

Appendix: source

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

	public CompletableFuture<Void> addPrompt(McpStatelessServerFeatures.PromptSpecification promptSpecification) {
		if (promptSpecification == null) {
			CompletableFuture<Void> future = new CompletableFuture<>();
			future.completeExceptionally(new McpError("Prompt specification must not be null"));
			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(() -> {
					String name = promptSpecification.getPrompt().getName();
					McpStatelessServerFeatures.PromptSpecification existing =
							this.prompts.putIfAbsent(name, promptSpecification);
					if (existing != null) {
						throw new CompletionException(new McpError("Prompt with name '" + name + "' already exists"));
					}
					logger.debug("Added prompt handler: {}", name);
				})
				.exceptionally(ex -> {
					Throwable cause = (ex instanceof CompletionException) ? ex.getCause() : ex;
					String name = promptSpecification.getPrompt().getName();
					logger.error("Error while adding prompt '{}'", name, cause);
					throw new CompletionException(cause);
				});
	}

	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) {

View on GitHub (pinned to 21cf2e9ba5)