conductor-oss/conductor · error · RuntimeException
Invalid JSON-RPC response: missing 'result' field
Error message
Invalid JSON-RPC response: missing 'result' field
What it means
Thrown by listToolsDirectHttp when the JSON-RPC response has neither an `error` nor a `result` field. Per JSON-RPC 2.0 a valid response to a request must contain exactly one of result/error; absence of both means the server returned a structurally non-conformant payload (e.g. just an ack, or an SSE event that was not a JSON-RPC response).
Source
Thrown at ai/src/main/java/org/conductoross/conductor/ai/mcp/MCPService.java:154
String contentType = response.contentType;
// Parse response based on content type
JsonNode responseJson;
if (contentType != null && contentType.contains("text/event-stream")) {
// Parse SSE format
responseJson = parseSseResponse(responseBody);
} else {
// Parse as JSON directly
responseJson = objectMapper.readTree(responseBody);
}
if (responseJson.has("error")) {
throw new RuntimeException(
"JSON-RPC error: " + responseJson.get("error").toString());
}
if (!responseJson.has("result")) {
throw new RuntimeException("Invalid JSON-RPC response: missing 'result' field");
}
JsonNode result = responseJson.get("result");
JsonNode toolsNode = result.get("tools");
if (toolsNode == null || !toolsNode.isArray()) {
throw new RuntimeException(
"Invalid response: 'tools' field is missing or not an array");
}
ExternalDataLimits.validateStructure(objectMapper.convertValue(result, Object.class));
// Convert to McpSchema.Tool list
// Use Jackson to deserialize tools directly (same pattern as stdio implementation)
List<McpSchema.Tool> tools =
objectMapper.convertValue(
toolsNode,
objectMapper
.getTypeFactory()View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Capture the raw response body to confirm what the server actually returned (it was logged at debug).
- Verify the endpoint is a JSON-RPC responder and not an event-stream info endpoint.
- Ensure the Accept header negotiated a transport the server uses to send the JSON-RPC result back.
- If the server only speaks SSE, confirm content-type detection worked so parseSseResponse was invoked.
Defensive patterns
Strategy: try-catch
Try / catch
try {
mcpService.listTools(serverUrl, headers);
} catch (RuntimeException e) {
if (e.getMessage().contains("missing 'result' field")) {
// server returned a non-JSON-RPC envelope; log body and check endpoint/transport
}
throw e;
} Prevention
- Verify the endpoint returns a JSON-RPC response object, not metadata or notifications.
- Capture raw bodies in debug logs to spot malformed envelopes.
- Confirm SSE vs JSON transport matches the server's actual response type.
When it happens
Trigger: Server returns `{"jsonrpc":"2.0","id":1}` with no result/error; server returns a notification-style or progress message as the response; SSE stream delivered only keep-alive/event frames and no data payload that resolved to a JSON-RPC response object.
Common situations: Hitting a server that streams server-sent events where the first non-data frames were concatenated; pointing at an endpoint that returns metadata instead of a JSON-RPC response; mismatched transport expectation (server is SSE-only but content-type was not text/event-stream).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid response: 'tools' field is missing or not an array
- HTTP %d error from MCP server: %s
- JSON-RPC error: {error}
- {error}
- No data found in SSE response: {sseBody}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/dd68b2c55a271035.
Report an issue: GitHub.