GoogleContainerTools/skaffold · error

service %q does not expose port %s

Error message

service %q does not expose port %s

What it means

findServicePort searches the service's spec.ports for a port matching the requested IntOrString (numeric or named). If no service port matches by number or name, it returns "service %q does not expose port %s". This is a configuration mismatch between the port the user asked to forward and the ports the Kubernetes Service actually declares.

Source

Thrown at pkg/skaffold/kubernetes/portforward/kubectl_forwarder.go:333

		tj := pods[j].CreationTimestamp.Time
		return ti.After(tj)
	}
}

func findServicePort(svc corev1.Service, servicePort schemautil.IntOrString) (corev1.ServicePort, error) {
	for _, s := range svc.Spec.Ports {
		switch servicePort.Type {
		case schemautil.Int:
			if s.Port == int32(servicePort.IntVal) {
				return s, nil
			}
		case schemautil.String:
			if s.Name == servicePort.StrVal {
				return s, nil
			}
		}
	}
	return corev1.ServicePort{}, fmt.Errorf("service %q does not expose port %s", svc.Name, servicePort.String())
}

func findTargetPort(svcPort corev1.ServicePort, pod corev1.Pod) int {
	if svcPort.TargetPort.Type == intstr.Int {
		return svcPort.TargetPort.IntValue()
	}
	for _, c := range pod.Spec.Containers {
		for _, p := range c.Ports {
			if svcPort.TargetPort.StrVal == p.Name {
				return int(p.ContainerPort)
			}
		}
	}
	return -1
}

View on GitHub (pinned to a1189de023)

Solutions

  1. Inspect the service's actual ports: `kubectl get svc <name> -o jsonpath='{.spec.ports}'` and request one of those ports (or its exact name) in the skaffold port-forward resource.
  2. If you meant to forward the container/target port, use the service's exposed port number instead.
  3. Add or rename the port in the Service manifest to match the requested name/number and redeploy.
  4. When the service exposes multiple ports, specify the exact port or portName in the port-forward config.

Example fix

// before: service exposes 80 but config forwards 8080
port: 8080
  localPort: 8080
// after
port: 80
  localPort: 8080
Defensive patterns

Strategy: validation

Validate before calling

svcObj, _ := client.CoreV1().Services(ns).Get(ctx, serviceName, metav1.GetOptions{})
for _, p := range svcObj.Spec.Ports {
    if int32(requestedPort) == p.Port || requestedName == p.Name {
        return nil // port is exposed by the service
    }
}
return fmt.Errorf("service %s exposes ports %+v; requested %v not found", serviceName, svcObj.Spec.Ports, requestedPort)

Type guard

func serviceExposesPort(svc corev1.Service, port schemautil.IntOrString) bool {
    for _, p := range svc.Spec.Ports {
        if port.Type == schemautil.Int && int32(port.IntVal) == p.Port { return true }
        if port.Type == schemautil.String && port.StrVal == p.Name { return true }
    }
    return false
}

Try / catch

if err := tryForward(ctx, svc, port); err != nil && strings.Contains(err.Error(), "does not expose port") {
    log.Errorf("%v — run `kubectl get svc %s -o yaml` and pick a declared port", err, svc)
}

Prevention

When it happens

Trigger: findServicePort(*svc, servicePort) iterates svc.Spec.Ports without matching: the requested numeric port is not in spec.ports[].port, or the requested string name does not equal any port's name.

Common situations: Port-forward config referencing the container port (e.g. 8080) instead of the service port (e.g. 80); referencing a named port that was renamed or omitted; multiple ports on the service and the wrong one requested; YAML edits that changed service ports after the skaffold config was written.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/1d3131208d55e232. Report an issue: GitHub.