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

  1. Log the op.SelfLink value and verify it is a full Google Cloud URL (project, and optionally zone/region, plus operation name)
  2. Retry the operation that produced the Operation object — a partial API response is often transient
  3. If in tests, make mocks use realistic SelfLinks like https://www.googleapis.com/compute/v1/projects/P/zones/Z/operations/opName
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/d91c6a803c81f695. Report an issue: GitHub.