zhisheng17/flink-learning · error · RuntimeException

Unrecognized Service type: {}

Error message

Unrecognized Service type: {}

What it means

Fabric8FlinkKubeClient.getRestPortFromExternalService resolves the REST port exposed by the Flink cluster's external Service. It handles ClusterIP and LoadBalancer (use the service port) and NodePort (use the node port), and throws this RuntimeException for any other Service type. It is a fail-fast guard against unsupported Kubernetes Service types.

Source

Thrown at flink-learning-k8s/flink-k8s/src/main/java/org/apache/flink/kubernetes/kubeclient/Fabric8FlinkKubeClient.java:431

		if (servicePortCandidates.isEmpty()) {
			throw new RuntimeException("Failed to find port \"" + Constants.REST_PORT_NAME + "\" in Service \"" +
				ExternalServiceDecorator.getExternalServiceName(this.clusterId) + "\"");
		}

		final ServicePort externalServicePort = servicePortCandidates.get(0);

		final KubernetesConfigOptions.ServiceExposedType externalServiceType =
			KubernetesConfigOptions.ServiceExposedType.valueOf(externalService.getSpec().getType());

		switch (externalServiceType) {
			case ClusterIP:
			case LoadBalancer:
				return externalServicePort.getPort();
			case NodePort:
				return externalServicePort.getNodePort();
			default:
				throw new RuntimeException("Unrecognized Service type: " + externalServiceType);
		}
	}

	private Optional<Endpoint> getRestEndPointFromService(Service service, int restPort) {
		if (service.getStatus() == null) {
			return Optional.empty();
		}

		LoadBalancerStatus loadBalancer = service.getStatus().getLoadBalancer();
		boolean hasExternalIP = service.getSpec() != null &&
			service.getSpec().getExternalIPs() != null && !service.getSpec().getExternalIPs().isEmpty();

		if (loadBalancer != null) {
			return getLoadBalancerRestEndpoint(loadBalancer, restPort);
		} else if (hasExternalIP) {
			final String address = service.getSpec().getExternalIPs().get(0);
			if (address != null && !address.isEmpty()) {
				return Optional.of(new Endpoint(address, restPort));

View on GitHub (pinned to d731cee761)

Solutions

  1. Set kubernetes.rest-service.exposed.type to ClusterIP, LoadBalancer, or NodePort.
  2. Inspect the deployed Service (kubectl get svc <cluster-id> -o jsonpath='{.spec.type}') and fix a manually/externally changed type.
  3. If a GitOps controller keeps rewriting the type, exclude the Flink Services from its management.

Example fix

// before
kubernetes.rest-service.exposed.type: ExternalName
// after
kubernetes.rest-service.exposed.type: LoadBalancer
Defensive patterns

Strategy: validation

Validate before calling

String type = flinkConfig.get(KubernetesConfigOptions.REST_SERVICE_EXPOSED_TYPE) != null ? flinkConfig.get(KubernetesConfigOptions.REST_SERVICE_EXPOSED_TYPE).name() : service.getSpec().getType();
if (!("ClusterIP".equals(type) || "LoadBalancer".equals(type) || "NodePort".equals(type))) {
    throw new IllegalStateException("Unsupported Service type for REST port lookup: " + type);
}

Try / catch

try {
    int port = kubeClient.getRestPort(clusterId);
} catch (RuntimeException e) {
    LOG.warn("Unsupported service type, cannot resolve REST port: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling restPort()/getRestPortFromExternalService when the external Flink REST Service's spec.type is anything other than ClusterIP, LoadBalancer, or NodePort — e.g. ExternalName, or a type set/patched to an unexpected value.

Common situations: Users set kubernetes.rest-service.exposed.type (or service.type) to an unsupported value, manually edit the Service YAML to ExternalName, or a controller/GitOps tool rewrites the Service type after deployment.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of zhisheng17/flink-learning@d731cee761 (2026-09-06). Data as JSON: /api/errors/46a80cafb32bd832. Report an issue: GitHub.