{"record":{"id":"00e4f3403a93f66a","repo":"kubernetes/kops","slug":"s-v","errorCode":null,"errorMessage":"%s: %v","messagePattern":"%s: %v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/assets/assetcopy/copy.go","lineNumber":107,"sourceCode":"\t}\n\n\tgotError := false\n\tnames := make([]string, 0, len(tasks))\n\tfor name := range tasks {\n\t\tnames = append(names, name)\n\t}\n\tsort.Strings(names)\n\tfor _, name := range names {\n\t\ttask := tasks[name]\n\t\terr := <-ch\n\t\tif err != nil {\n\t\t\tklog.Warning(err)\n\t\t\tgotError = true\n\t\t}\n\t\tgo func(n string, t assetTask) {\n\t\t\terr := t.Run()\n\t\t\tif err != nil {\n\t\t\t\terr = fmt.Errorf(\"%s: %v\", n, err)\n\t\t\t}\n\t\t\tch <- err\n\t\t}(name, task)\n\t}\n\n\tfor i := 0; i < cap(ch); i++ {\n\t\terr := <-ch\n\t\tif err != nil {\n\t\t\tklog.Warning(err)\n\t\t\tgotError = true\n\t\t}\n\t}\n\n\tclose(ch)\n\tif gotError {\n\t\treturn fmt.Errorf(\"not all assets copied successfully\")\n\t}\n\treturn nil","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/assets/assetcopy/copy.go#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the asset name prefix, then diagnose the underlying error after the colon (often 'unable to transfer ...' or an upload/write error).","Verify the source asset URL is reachable from the machine running kops (curl/HEAD the canonical URL).","Re-run `kops get assets --copy`; the channel-based task loop retries only on a fresh invocation.","If the same asset fails repeatedly, check the asset's sha in the cluster spec against the actual upstream file."],"exampleFix":"// before (observed log)\nW  https://storage.googleapis.com/k8s-artifacts-prod/kube-proxy.tar.gz: unable to transfer ... : context deadline exceeded\n// after (fix upstream cause, e.g. retry with network access restored)\nkops get assets --copy --output <spec>  # succeeds once source is reachable","handlingStrategy":"try-catch","validationCode":"// Pre-check that each asset's source URL is reachable before copying:\nfor _, name := range assetNames {\n    resp, err := http.Head(sourceURL(name))\n    if err != nil || resp.StatusCode >= 400 {\n        log.Printf(\"asset %s unreachable: %v\", name, err)\n    }\n}","typeGuard":"// Go has no runtime type guard needed; narrow the wrapped error by inspecting the message prefix:\nfunc assetNameFromError(err error) (string, bool) {\n    if err == nil { return \"\", false }\n    if i := strings.Index(err.Error(), \": \"); i > 0 { return err.Error()[:i], true }\n    return \"\", false\n}","tryCatchPattern":"if err := assetcopy.Copy(imageAssets, fileAssets, vfsContext, cluster); err != nil {\n    // per-asset failures were already klog.Warning'd with \"<asset>: <cause>\"\n    return fmt.Errorf(\"asset copy incomplete, see warnings above: %w\", err)\n}","preventionTips":["Run kops from a host with egress to all upstream asset hosts","Pre-verify asset URLs with curl -I before bulk copy","Use -v=4 to get per-asset diagnostics","Re-run after transient failures; matching assets are skipped"],"tags":["go","error-wrapping","asset-copy","concurrency"],"backgroundTag":"asset-copy-task-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}