kubernetes/kops · error
error parsing operation URL %q: %v
Error message
error parsing operation URL %q: %v
What it means
WaitForOp parses the operation's SelfLink via ParseGoogleCloudURL to decide whether the operation is zonal, regional, or global. If the SelfLink cannot be parsed as a Google Cloud URL, this error is returned immediately instead of polling. It indicates the compute.Operation object contains a malformed or unexpected SelfLink.
Source
Thrown at upup/pkg/fi/cloudup/gce/op.go:40
import (
"fmt"
"time"
compute "google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
)
const (
operationPollInterval = 3 * time.Second
operationPollTimeoutDuration = 30 * time.Minute
)
func WaitForOp(client *compute.Service, op *compute.Operation) error {
u, err := ParseGoogleCloudURL(op.SelfLink)
if err != nil {
return fmt.Errorf("error parsing operation URL %q: %v", op.SelfLink, err)
}
if u.Zone != "" {
return waitForZoneOp(client, op)
}
if u.Region != "" {
return waitForRegionOp(client, op)
}
return waitForGlobalOp(client, op)
}
func waitForZoneOp(client *compute.Service, op *compute.Operation) error {
u, err := ParseGoogleCloudURL(op.SelfLink)
if err != nil {
return fmt.Errorf("error parsing operation URL %q: %v", op.SelfLink, err)
}View on GitHub (pinned to 4c8573c808)
Solutions
- Log the op.SelfLink value and verify it is a full Google Cloud URL (project, and optionally zone/region, plus operation name)
- Retry the operation that produced the Operation object — a partial API response is often transient
- If in tests, make mocks use realistic SelfLinks like https://www.googleapis.com/compute/v1/projects/P/zones/Z/operations/opName
- Upgrade kops / google-api-go-client in case of a SelfLink format change
Example fix
// before
op := &compute.Operation{Name: "op-1"}
err := WaitForOp(client, op)
// after
op := &compute.Operation{Name: "op-1", SelfLink: "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/operations/op-1"}
err := WaitForOp(client, op) Defensive patterns
Strategy: validation
Validate before calling
func validOpSelfLink(op *compute.Operation) bool {
_, err := gce.ParseGoogleCloudURL(op.SelfLink)
return err == nil
}
if !validOpSelfLink(op) { return fmt.Errorf("operation %s has invalid SelfLink %q", op.Name, op.SelfLink) } Try / catch
if err := gce.WaitForOp(client, op); err != nil {
if strings.Contains(err.Error(), "error parsing operation URL") {
klog.Errorf("bad op SelfLink %q — refresh op via compute API and retry", op.SelfLink)
}
return err
} Prevention
- Always obtain Operation objects from real compute API responses, never construct them by hand outside tests
- In tests, populate SelfLink with canonical GCE URLs
- Verify proxies/custom endpoints do not rewrite self-links
- Refresh the operation from the API if its SelfLink looks empty or truncated
When it happens
Trigger: A compute.Operation returned by the API (or fabricated in tests/mocks) whose SelfLink field is empty, truncated, or in an unexpected format, passed into WaitForOp.
Common situations: Mock/stub operations in tests with fake SelfLinks; API responses from unusual endpoints or proxies; bugs in constructing operations when the compute API returns partial objects.
Related errors
- unable to parse instance url %q
- invalid google cloud URL (content after name): %q
- error parsing subnet url %q: %w
- error creating forwarding rule: %v
- setting ForwardRule labels: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d91c6a803c81f695.
Report an issue: GitHub.