alibaba/nacos · error · IllegalStateException

Failed to parse response body

Error message

Failed to parse response body

What it means

Thrown by McpExternalDataAdaptor.fetchUrlPage when the HTTP body from the registry cannot be deserialized into McpRegistryServerList. The response was 2xx but its JSON shape did not match the expected schema. It is an IllegalStateException wrapping the original parse exception.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/McpExternalDataAdaptor.java:198

        int code = resp.statusCode();
        if (!isSuccessStatus(code)) {
            throw new IllegalStateException("HTTP " + code + " when fetching " + pageUrl);
        }
        List<McpServerDetailInfo> servers = null;
        String next = null;
        try {
            McpRegistryServerList listPage =
                JacksonUtils.toObj(resp.body(), McpRegistryServerList.class);
            if (listPage != null && listPage.getServers() != null) {
                servers = listPage.getServers().stream()
                    .map(this::adaptOfficialMcpServerFromResponse)
                    .collect(Collectors.toList());
            }
            if (listPage != null && listPage.getMetadata() != null) {
                next = listPage.getMetadata().getNextCursor();
            }
        } catch (Exception e) {
            throw new IllegalStateException("Failed to parse response body", e);
        }
        return new UrlPageResult(servers, next);
    }
    
    private List<McpServerDetailInfo> fetchUrlServersAll(String urlData, String search)
        throws Exception {
        List<McpServerDetailInfo> collected = new ArrayList<>();
        String cursor = null;
        int pages = 0;
        while (pages < MAX_PAGES_GUARD) {
            pages++;
            UrlPageResult page = fetchUrlPage(urlData, cursor, 30, search);
            if (CollectionUtils.isNotEmpty(page.getServers())) {
                collected.addAll(page.getServers());
            }
            String next = page.getNextCursor();
            if (next == null) {
                break;

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Confirm the URL points to an endpoint implementing the official MCP registry openapi contract.
  2. Fetch the URL manually and inspect the body to confirm it is the expected JSON shape.
  3. Update the adaptor/SDK if the registry schema changed, or pin to a compatible registry version.

Example fix

// before
// url returns {"items": [...]} instead of {"servers": [...]} -> parse error
String url = "https://example.com/api/items";

// after
// use an endpoint conforming to McpRegistryServerList schema
String url = "https://registry.modelcontextprotocol.org/v0/servers";
Defensive patterns

Strategy: try-catch

Try / catch

try { adaptor.fetchOfficialRegistryPage(url, c, l, s); }
catch (IllegalStateException e) { if (e.getMessage().contains("parse")) reportSchemaMismatch(url); }

Prevention

When it happens

Trigger: The endpoint returned valid JSON but not the McpRegistryServerList shape (missing 'servers'/'metadata'); the endpoint returned HTML (e.g. a login page or error page) with a 200 status; a registry API version change altered the payload contract.

Common situations: Pointing the URL import at a non-registry JSON endpoint; registry API contract drift after an upgrade; a transparent proxy returning an HTML interstitial with 200.

Understand the failure class

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/4ce6eb1a96710656. Report an issue: GitHub.