kubernetes/kops · error

%s: %v

Error message

%s: %v

What it means

Copy() runs each asset copy task in a bounded worker-slot goroutine (cap-5 buffered channel used as a semaphore). When a task's Run() fails, the error is wrapped with the asset name via fmt.Errorf("%s: %v", n, err) before being sent on the channel, so the klog warning names which asset failed. It is a wrapper, not a root cause; the underlying error follows the colon.

Source

Thrown at pkg/assets/assetcopy/copy.go:107

	}

	gotError := false
	names := make([]string, 0, len(tasks))
	for name := range tasks {
		names = append(names, name)
	}
	sort.Strings(names)
	for _, name := range names {
		task := tasks[name]
		err := <-ch
		if err != nil {
			klog.Warning(err)
			gotError = true
		}
		go func(n string, t assetTask) {
			err := t.Run()
			if err != nil {
				err = fmt.Errorf("%s: %v", n, err)
			}
			ch <- err
		}(name, task)
	}

	for i := 0; i < cap(ch); i++ {
		err := <-ch
		if err != nil {
			klog.Warning(err)
			gotError = true
		}
	}

	close(ch)
	if gotError {
		return fmt.Errorf("not all assets copied successfully")
	}
	return nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the asset name prefix, then diagnose the underlying error after the colon (often 'unable to transfer ...' or an upload/write error).
  2. Verify the source asset URL is reachable from the machine running kops (curl/HEAD the canonical URL).
  3. Re-run `kops get assets --copy`; the channel-based task loop retries only on a fresh invocation.
  4. If the same asset fails repeatedly, check the asset's sha in the cluster spec against the actual upstream file.

Example fix

// before (observed log)
W  https://storage.googleapis.com/k8s-artifacts-prod/kube-proxy.tar.gz: unable to transfer ... : context deadline exceeded
// after (fix upstream cause, e.g. retry with network access restored)
kops get assets --copy --output <spec>  # succeeds once source is reachable
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that each asset's source URL is reachable before copying:
for _, name := range assetNames {
    resp, err := http.Head(sourceURL(name))
    if err != nil || resp.StatusCode >= 400 {
        log.Printf("asset %s unreachable: %v", name, err)
    }
}

Type guard

// Go has no runtime type guard needed; narrow the wrapped error by inspecting the message prefix:
func assetNameFromError(err error) (string, bool) {
    if err == nil { return "", false }
    if i := strings.Index(err.Error(), ": "); i > 0 { return err.Error()[:i], true }
    return "", false
}

Try / catch

if err := assetcopy.Copy(imageAssets, fileAssets, vfsContext, cluster); err != nil {
    // per-asset failures were already klog.Warning'd with "<asset>: <cause>"
    return fmt.Errorf("asset copy incomplete, see warnings above: %w", err)
}

Prevention

When it happens

Trigger: Any failure returned by CopyFile.Run() or CopyImage.Run() during `kops get assets --copy` — e.g. download failure, sha mismatch, or upload failure — is prefixed with the asset's canonical URL/name at copy.go:107.

Common situations: A single unreachable file repository or container registry among many assets; one corrupted asset whose sha does not match; transient network errors while copying hundreds of assets.

Related errors


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