theonedev/onedev · error · ExplicitException

Tool not found: ${toolName}

Error message

Tool not found: ${toolName}

What it means

After forwarding a tool call to the client, the service obtains an AiToolExecution future used to collect the tool's result. A null future means no registered handler/tool matched the requested tool name, so the call can never complete and the service fails fast with this error.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/DefaultChatService.java:327

							try {
								var aiMessage = completeResponse.aiMessage();
								if (aiMessage.hasToolExecutionRequests()) {
									langchain4jMessages.add(aiMessage);
									var toolRequests = aiMessage.toolExecutionRequests();
									var connectionRegistry = WebSocketSettings.Holder.get(application).getConnectionRegistry();
									var connection = connectionRegistry.getConnection(application, sessionId, pageKey);
									if (connection == null || !connection.isOpen())
										throw new ExplicitException("Conversation context lost");
									for (var toolRequest: toolRequests) {
										if (responseFuture.isDone())										
											return;
										String toolName = toolRequest.name();
										try {
											var toolExecution = new AiToolExecution(toolName, ToolUtils.getToolArguments(toolRequest));
											connection.sendMessage(toolExecution);
											var toolExecutionFuture = toolExecution.getFuture();
											if (toolExecutionFuture == null)
												throw new ExplicitException("Tool not found: " + toolName);
											while (true) {
												try {
													var toolExecutionResult = toolExecutionFuture.get(1, TimeUnit.SECONDS);
													toolExecutionResult.addToMessages(langchain4jMessages, toolRequest);
													break;
												} catch (TimeoutException e) {
													if (responseFuture.isDone())
														return;
												} catch (CancellationException e) {
													// may get cancelled in DefaultManagedFutureService
													throw new ExplicitException("Timed out calling tool: " + toolName);
												}
											}
										} catch (Throwable t) {
											ToolUtils.handleCallException(toolName, t);
										}
									}
									

View on GitHub (pinned to d44925c47c)

Solutions

  1. Verify the tool is registered server-side (check tool definitions exposed to the model) and matches the name casing the model received
  2. Update OneDev / AI tool definitions so the model's tool list matches available handlers
  3. Clear the chat and start a new conversation so the model re-fetches the current tool specs
  4. If you added custom tools, confirm they are contributed before the chat session starts

Example fix

// before: model requests 'listAllFiles' which is not registered
// after: constrain the model to registered tools / validate names before sending
if (ToolUtils.findTool(toolName) == null) {
    logger.warn("Model requested unknown tool: " + toolName);
    return; // or send a tool-error result instead of throwing
}
Defensive patterns

Strategy: validation

Validate before calling

// before relying on a tool, confirm it is registered/exposed to the model
boolean known = availableToolNames.stream().anyMatch(n -> n.equals(toolName));
if (!known) throw new IllegalArgumentException("Unknown tool: " + toolName);

Try / catch

try {
    chatService.chat(chatId, prompt);
} catch (ExplicitException e) {
    if (e.getMessage().startsWith("Tool not found: ")) {
        String tool = e.getMessage().substring("Tool not found: ".length());
        // refresh tool specs / start new conversation
    }
}

Prevention

When it happens

Trigger: The LLM emitted a toolExecutionRequest whose name does not correspond to any tool registered/executable for this conversation, so toolExecution.getFuture() returns null in onCompleteResponse.

Common situations: Model hallucinating a tool name not in the tool spec; tool registry changed between model training/context and current server version; custom tools not registered on the server; typo or casing mismatch in tool definitions.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/f82892102fe28083. Report an issue: GitHub.