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.
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)
Solutions
- Track registered prompt names and remove only those present.
- Make teardown idempotent with exceptionally(ex -> null).
- Reuse the exact name string from registration.
- 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
- Track registered prompt names locally.
- Make teardown idempotent.
- Reuse the exact registered name.
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
- Prompt with name '{}' already exists
- Prompt with name '${promptName}' already exists
- Prompt with name '${promptName}' not found
- Tool with name '{}' already exists
- Tool with name '{}' not found
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/82ba25edd577174f.
Report an issue: GitHub.