cilium/cilium · error
No reconciler available for GVK %s
Error message
No reconciler available for GVK %s
What it means
registerReconcilers iterates over the list of optional Gateway API CRDs that were autodetected as installed in the cluster and, for each one, either logs that support is enabled or (in the default case) panics. The panic means the operator was told a CRD is installed that has no case in this switch — i.e. an optional GVK was added to the optionalGVKs list without a matching reconciler branch. It is an internal invariant violation, a programmer error, not a user configuration error.
Source
Thrown at operator/pkg/gateway-api/cell.go:464
switch gvk.Kind {
case helpers.TCPRouteKind:
// TCPRoute is reconciled by the Gateway API reconciler, but log that the
// support has been successfully enabled.
logger.Info("TCPRoute CRD is installed, TCPRoute support is enabled")
case helpers.UDPRouteKind:
// UDPRoute is reconciled by the Gateway API reconciler, but log that the
// support has been successfully enabled.
logger.Info("UDPRoute CRD is installed, UDPRoute support is enabled")
case helpers.ListenerSetKind:
// ListenerSet is reconciled by the Gateway API reconciler, but log that the
// support has been successfully enabled.
logger.Info("ListenerSet CRD is installed, ListenerSet support is enabled")
case helpers.ServiceImportKind:
// we don't need a reconciler, but we do need to tell folks that the
// support is working.
logger.Info("ServiceImport CRD is installed, ServiceImport support is enabled")
default:
panic(fmt.Sprintf("No reconciler available for GVK %s", gvk))
}
}
return nil
}
func registerGatewayAPITypesToScheme(scheme *runtime.Scheme, optionalKinds []schema.GroupVersionKind) error {
// Autodetection of installed types means we have to add things to the scheme
// ourselves for non-Standard GroupVersions, we can't use the generated
// functions.
addToSchema := make(map[fmt.Stringer]func(s *runtime.Scheme) error)
// Install all required GVKs.
for _, gvk := range helpers.RequiredGVKs {
addToSchema[gvk] = func(s *runtime.Scheme) error {
s.AddKnownTypes(
gvk.GroupVersion(),
helpers.GetConcreteObject(gvk),View on GitHub (pinned to ac7b90affa)
Solutions
- Check which GVK is printed in the panic and confirm whether it should be a supported optional kind
- If it is a new optional kind, add a case for it in the switch in registerReconcilers (operator/pkg/gateway-api/cell.go) that logs or registers a reconciler
- Verify the optionalGVKs list matches the kinds the build supports; pin to a released operator image that supports your CRD set
- If the CRD is not actually needed, remove it from the cluster or exclude it from the operator's detected CRD list
Example fix
// before
default:
panic(fmt.Sprintf("No reconciler available for GVK %s", gvk))
// after
default:
logger.Warn("No reconciler available for GVK, skipping", logfields.OptionalGVK, gvk) // or add a case for the new kind
// case helpers.MyNewRouteKind: logger.Info("MyNewRoute CRD is installed, support enabled") Defensive patterns
Strategy: validation
Validate before calling
supported := map[string]bool{helpers.TCPRouteKind: true, helpers.UDPRouteKind: true, helpers.ListenerSetKind: true, helpers.ServiceImportKind: true}
if !supported[gvk.Kind] {
return fmt.Errorf("optional GVK %s has no reconciler support in this build", gvk)
} Type guard
func isSupportedOptionalKind(gvk schema.GroupVersionKind) bool {
switch gvk.Kind {
case helpers.TCPRouteKind, helpers.UDPRouteKind, helpers.ListenerSetKind, helpers.ServiceImportKind:
return true
}
return false
} Prevention
- Keep optionalGVKs and the switch in registerReconcilers in sync — add the switch case in the same commit as a new GVK
- Run the operator's unit/e2e tests with all optional CRDs installed before shipping a build with new kinds
- Prefer logging and skipping over panic for optional-feature detection
When it happens
Trigger: A new optional GVK is added to the optionalGVKs global (or modified via config/CLI) and its Kind reaches the switch without a matching case, e.g. someone patches the operator to treat a custom CRD (like a new xRoute type) as an optional kind, or a development build diverges from the switch statement.
Common situations: Running a custom/dev build of the Cilium operator where optionalGVKs was extended; misconfigured Helm/CLI flags injecting unexpected GVKs; version skew where a newer CRD list is fed to an older switch statement.
Related errors
- failed to get backend Service %s: %w
- failed to patch frontend EndpointSlice: %w
- no Accepted Listeners for Gateway
- Tried to get a concrete type that is not implemented, %s
- Tried to get a concrete list type that is not implemented, %
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/a9a47e2b0bdd57f0.
Report an issue: GitHub.