tailscale/tailscale · error
error creating Tailscale Service: %w
Error message
error creating Tailscale Service: %w
What it means
Thrown by HAIngressReconciler.maybeProvision when tsClient.VIPServices().CreateOrUpdate fails to create or update the Tailscale Service (VIPService) named svc:<hostname> on the control plane. It can also wrap upstream refusals from owner handling: an existing VIPService without the tailscale.com/owner-references annotation (likely created outside the operator) is rejected rather than adopted, as is one already owned by another resource. Tailscale Services are an alpha tailnet feature, so a tailnet without it enabled also fails here.
Source
Thrown at cmd/k8s-operator/ingress-for-pg.go:363
Name: serviceName.String(),
Tags: tags,
Ports: tsSvcPorts,
Comment: managedTSServiceComment,
Annotations: updatedAnnotations,
}
if existingTSSvc != nil {
tsSvc.Addrs = existingTSSvc.Addrs
}
// TODO(irbekrm): right now if two Ingress resources attempt to apply different Tailscale Service configs (different
// tags, or HTTP endpoint settings) we can end up reconciling those in a loop. We should detect when an Ingress
// with the same generation number has been reconciled ~more than N times and stop attempting to apply updates.
if existingTSSvc == nil ||
!reflect.DeepEqual(tsSvc.Tags, existingTSSvc.Tags) ||
!reflect.DeepEqual(tsSvc.Ports, existingTSSvc.Ports) ||
!ownersAreSetAndEqual(tsSvc, *existingTSSvc) {
logger.Infof("Ensuring Tailscale Service exists and is up to date")
if err := tsClient.VIPServices().CreateOrUpdate(ctx, tsSvc); err != nil {
return false, fmt.Errorf("error creating Tailscale Service: %w", err)
}
}
// 5. Update tailscaled's AdvertiseServices config, which should add the Tailscale Service
// IPs to the ProxyGroup Pods' AllowedIPs in the next netmap update if approved.
mode := serviceAdvertisementHTTPS
if isHTTPEndpointEnabled(ing) || isHTTPRedirectEnabled(ing) {
mode = serviceAdvertisementHTTPAndHTTPS
}
if err = r.maybeUpdateAdvertiseServicesConfig(ctx, serviceName, mode, pg); err != nil {
return false, fmt.Errorf("failed to update tailscaled config: %w", err)
}
// 6. Update Ingress status if ProxyGroup Pods are ready.
count, err := numberPodsAdvertising(ctx, r.Client, r.tsNamespace, pg.Name, serviceName.String())
if err != nil {
return false, fmt.Errorf("failed to check if any Pods are configured: %w", err)
}View on GitHub (pinned to cfe32b8be6)
Solutions
- Read the wrapped message: feature-not-enabled means enable Tailscale Services for the tailnet; ACL/tag errors mean update the tailnet policy so the operator can create VIPServices with those tags.
- Check for a foreign VIPService named svc:<hostname> (admin console or API); if it predates the operator, rename the Ingress hostname or delete the VIPService.
- Verify the operator's control-plane credentials are valid and egress to the control plane is allowed.
- Transient 5xx/network failures resolve via reconcile backoff; check kubectl events on the Ingress for the outcome.
Defensive patterns
Strategy: validation
Validate before calling
// before exposing, ensure the VIPService name is free or operator-owned
name := "svc:" + hostname
if svc, err := tsClient.VIPServices().Get(ctx, name); err == nil {
if svc.Annotations["tailscale.com/owner-references"] == "" {
return fmt.Errorf("%s exists but is not operator-owned; delete it or rename the Ingress", name)
}
} Type guard
func isPolicyErr(err error) bool { // permanent: do not hot-retry
return err != nil && (strings.Contains(err.Error(), "not permitted") ||
strings.Contains(err.Error(), "feature") ||
strings.Contains(err.Error(), "owner annotation"))
} Try / catch
if err := tsClient.VIPServices().CreateOrUpdate(ctx, tsSvc); err != nil {
if isPolicyErr(err) {
r.recorder.Event(ing, corev1.EventTypeWarning, "VIPServiceRejected", err.Error())
return false, nil // surface to the user; stop error-looping
}
return false, fmt.Errorf("error creating Tailscale Service: %w", err) // transient: backoff requeue
} Prevention
- Enable the Tailscale Services feature on the tailnet before creating ProxyGroup Ingresses.
- Never create svc: VIPServices by hand; let the operator own that namespace.
- Restrict the tailscale.com/tags annotation to tags the operator device is granted.
- Rotate control-plane API credentials before they expire.
When it happens
Trigger: Tailscale Services (VIPServices) alpha feature not enabled on the tailnet; the operator device lacks ACL permission to create VIPServices or assign the tags requested via the tailscale.com/tags annotation; control plane 5xx or network failure; an existing svc:<hostname> VIPService created by hand without/with foreign owner annotations; invalid tags or description rejected by the API.
Common situations: Tailnet policy not updated before adopting ProxyGroup Ingresses; operator API credentials expired or revoked; Ingress hostname collides with a manually created VIPService; annotation tags not granted to the operator device.
Related errors
- getting Tailscale Service %q: %w
- deleting Tailscale Service %q: %w
- error getting Tailscale Service: %w
- tailscale.ACL: %w
- tailscale.ACLHuJSON: %w
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/dfb04cbfc8877bfd.
Report an issue: GitHub.