{"id":"0ee1155059c3cd02","repo":"apache/kafka","slug":"expected-response-from-controller-endpoint-but-go","errorCode":null,"errorMessage":"Expected response from CONTROLLER endpoint, but got response from endpoint type {endpointType}","messagePattern":"Expected response from CONTROLLER endpoint, but got response from endpoint type (.+?)","errorType":"exception","errorClass":"MismatchedEndpointTypeException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java","lineNumber":1808,"sourceCode":"                    metadataManager.updateFailed(e);\n                    return false;\n                }\n\n                @Override\n                public void handleFailure(Throwable e) {\n                    metadataManager.updateFailed(e);\n                }\n            };\n        }\n    }\n\n    static Cluster parseDescribeClusterResponse(DescribeClusterResponseData response) {\n        ApiError apiError = new ApiError(response.errorCode(), response.errorMessage());\n        if (apiError.isFailure()) {\n            throw apiError.exception();\n        }\n        if (response.endpointType() != EndpointType.CONTROLLER.id()) {\n            throw new MismatchedEndpointTypeException(\"Expected response from CONTROLLER \" +\n                \"endpoint, but got response from endpoint type \" + (int) response.endpointType());\n        }\n        List<Node> nodes = new ArrayList<>();\n        Node controllerNode = null;\n        for (DescribeClusterResponseData.DescribeClusterBroker node : response.brokers()) {\n            Node newNode = new Node(node.brokerId(), node.host(), node.port(), node.rack());\n            nodes.add(newNode);\n            if (node.brokerId() == response.controllerId()) {\n                controllerNode = newNode;\n            }\n        }\n        return new Cluster(response.clusterId(),\n            nodes,\n            Collections.emptyList(),\n            Collections.emptySet(),\n            Collections.emptySet(),\n            controllerNode);\n    }","sourceCodeStart":1790,"sourceCodeEnd":1826,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java#L1790-L1826","documentation":"Thrown by KafkaAdminClient.parseDescribeClusterResponse when a DescribeCluster response indicates it came from an endpoint whose type is not CONTROLLER, while the client expected a controller response (this path is taken when bootstrapping/operating against KRaft controllers). The MismatchedEndpointTypeException signals that the cluster metadata handshake routed the request to a broker-style endpoint instead of a controller, so the response cannot be trusted as controller-authoritative.","triggerScenarios":"describeCluster (or internal metadata refresh) issued against a bootstrap.controllers-configured Admin client where the server returned a DescribeClusterResponse with endpointType != EndpointType.CONTROLLER.id; happens inside the call's handleResponse -> parseDescribeClusterResponse when the active node is not advertising itself as a controller.","commonSituations":"bootstrap.controllers pointing at broker ports instead of KRaft controller listener ports; mixed-version cluster during upgrade where some nodes don't populate endpointType correctly; network/LB in front of the cluster routing controller-bound traffic to a broker; pointing an old client at a new cluster or vice versa where the DescribeCluster V# endpoint-type field semantics differ.","solutions":["Verify bootstrap.controllers host:port values target the controller listener (typically port 9093 / the KRaft controller listener), not the broker listener.","If you actually want broker-side metadata, use bootstrap.servers instead of bootstrap.controllers.","Check cluster health: ensure KRaft controllers are elected and reachable, and that no load balancer/proxy is rewriting the connection to a broker.","Confirm client and broker versions are compatible for the DescribeCluster API version in use."],"exampleFix":"// before - controller ports actually point at brokers\nprops.put(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG, \"host1:9092,host2:9092\");\nAdmin admin = Admin.create(props);\nadmin.describeCluster().all().get(); // MismatchedEndpointTypeException\n\n// after - point at the KRaft controller listener\nprops.put(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG, \"host1:9093,host2:9093\");\nAdmin admin = Admin.create(props);\nadmin.describeCluster().all().get();","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"int attempts = 0;\nwhile (true) {\n    try {\n        DescribeClusterResult r = admin.describeCluster(opts).nodes().get();\n        break;\n    } catch (ExecutionException e) {\n        if (e.getCause() instanceof MismatchedEndpointTypeException && attempts++ < 3) {\n            continue; // broker returned wrong endpoint type; retry after metadata refresh\n        }\n        throw e;\n    }\n}","preventionTips":["This is a server-side protocol mismatch (DescribeCluster answered with a non-CONTROLLER endpoint) — usually transient or broker-version-related; retry with backoff.","If it persists, switch the client from bootstrap.controllers to bootstrap.servers, or upgrade the broker to a version whose DescribeCluster honors the requested endpoint type.","Do not treat it as a programmer error; it surfaces from parseDescribeClusterResponse, not from caller input."],"tags":["admin-client","kraf","describe-cluster","endpoint","configuration"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}