microsoft/aspire · error · InvalidOperationException
Gateway ' ' must have a GatewayClassName set via…
Error message
Gateway '{gatewayResource.Name}' must have a GatewayClassName set via WithGatewayClass(). The Gateway API requires a gatewayClassName to select the controller implementation. What it means
The Kubernetes Gateway API requires every Gateway manifest to specify a gatewayClassName that selects the implementing controller. When publishing, KubernetesEnvironmentResource validates each gateway resource and throws InvalidOperationException if GatewayClassName was never set via WithGatewayClass.
Solutions
- Call WithGatewayClass("<controller-class>") on the gateway resource, e.g. WithGatewayClass("istio") or the class name of your Gateway controller.
- Verify the GatewayClass exists in the target cluster and matches your installed controller.
- Re-publish after setting the gateway class.
Example fix
// before
var gateway = env.AddGateway("public-gw").WithHostname("app.example.com");
// after
var gateway = env.AddGateway("public-gw")
.WithGatewayClass("istio")
.WithHostname("app.example.com"); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(gateway.GatewayClassName)) throw new InvalidOperationException("Gateway requires WithGatewayClass before publishing."); Try / catch
try { PublishAsync(); } catch (InvalidOperationException ex) when (ex.Message.Contains("WithGatewayClass")) { /* set the gateway class and re-publish */ } Prevention
- Always call WithGatewayClass when creating a gateway
- Keep the controller's gateway class name in a shared constant
- Validate gateway configuration in CI publish smoke tests
When it happens
Trigger: Adding a gateway resource to a Kubernetes environment and publishing without calling WithGatewayClass on it.
Common situations: Forgetting the gateway-class step when first setting up Kubernetes Gateway API ingress; templates/samples predating the WithGatewayClass requirement; a Gateway controller (e.g. Istio, Envoy Gateway) migration where the class name is now mandatory.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Gateway ' ' was not assigned a hostname address within the…
- Gateway ' ' configures hostnames that would be inherited by…
- Path must start with '/'.
- Resource ' ' is configured to publish as a Kubernetes…
- Unknown gateway path match type
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/9e2c61ffc912e121.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs:1067
}
}
else if (!string.IsNullOrEmpty(DefaultStorageClassName))
{
claim.Spec.StorageClassName = DefaultStorageClassName;
}
return claim;
}
private async Task BuildGatewayObjects(
KubernetesGatewayResource gatewayResource,
Dictionary<IResource, KubernetesResource> deploymentTargets,
ILogger logger,
CancellationToken cancellationToken)
{
if (gatewayResource.GatewayClassName is null)
{
throw new InvalidOperationException(
$"Gateway '{gatewayResource.Name}' must have a GatewayClassName set via WithGatewayClass(). " +
$"The Gateway API requires a gatewayClassName to select the controller implementation.");
}
var gatewayName = gatewayResource.Name.ToKubernetesResourceName();
// This whole method re-runs when the deployment-target step executes a second time (once for
// "before-start", once in the publish/deploy DAG). GeneratedGateway is assigned so it replaces
// itself, but GeneratedHttpRoutes is appended to — without clearing, every route is emitted
// twice and the chart renders duplicate HTTPRoute objects with identical names.
gatewayResource.GeneratedHttpRoutes.Clear();
var gateway = new GatewayV1
{
Metadata = { Name = gatewayName }
};
var resolvedHostnames = await ResolveHostnamesAsync(
gatewayResource.Hostnames,View on GitHub (pinned to 25830f84bd)