conductor-oss/conductor · error · RuntimeException

Failed to call MCP tool '{toolName}' on {serverUrl}: {messag

Error message

Failed to call MCP tool '{toolName}' on {serverUrl}: {message}

What it means

Catch-all wrapper thrown by callToolDirectHttp's outer catch (Exception). Wraps ANY exception from the tool-call flow (165/166/167, SSE parse 169/170, redirect 171-173, payload limit 175/176, or network IOException) with toolName, serverUrl, original message, and the cause. This is the exception callers of callTool see for almost every failure.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java:289

            // Process the result JSON to parse text content as JSON where applicable
            processResultJson(resultNode);

            // Return as Map to preserve parsed field
            Map<String, Object> result = objectMapper.convertValue(resultNode, Map.class);
            ExternalDataLimits.validateStructure(result);

            log.debug(
                    "Successfully called tool '{}' via direct JSON-RPC on {}", toolName, serverUrl);
            return result;

        } catch (Exception e) {
            log.error(
                    "Failed to call tool '{}' via direct JSON-RPC on {}: {}",
                    toolName,
                    serverUrl,
                    e.getMessage());
            throw new RuntimeException(
                    "Failed to call MCP tool '"
                            + toolName
                            + "' on "
                            + serverUrl
                            + ": "
                            + e.getMessage(),
                    e);
        }
    }

    /**
     * Processes a CallToolResult JSON node to parse JSON strings in text content.
     *
     * <p>Modifies the JSON response before deserialization to convert JSON strings to objects.
     */
    private void processResultJson(JsonNode resultNode) {
        if (resultNode == null || !resultNode.has("content")) {
            return;

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect e.getCause() for the real failure; the wrapper text alone is insufficient.
  2. Map the cause to its specific error (165-167, 169-170, 171-176) and apply that fix.
  3. For transient network causes, retry with backoff.
  4. Log the unwrapped cause chain so dashboards show root reasons.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    Map<String,Object> r = mcpService.callTool(serverUrl, toolName, arguments, headers);
} catch (RuntimeException e) {
    Throwable root = e;
    while (root.getCause() != null && root.getCause() != root) root = root.getCause();
    log.error("callTool '{}' failed for {}: rootCause={}", toolName, serverUrl, root.toString());
    throw e;
}

Prevention

When it happens

Trigger: Any uncaught exception inside callToolDirectHttp's try: network timeout, SSL/DNS failure, JSON-RPC protocol error, redirect/credential/payload violation, or one of errors 165-167/169/170.

Common situations: Server unreachable; auth expired; tool crashed; arguments invalid. The wrapper hides the root cause behind a generic prefix — operators must read getCause().

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/25dd036505d3ed3f. Report an issue: GitHub.