{"record":{"id":"e2da12f107ae5efb","repo":"kubernetes/kops","slug":"error-downloading-content-from-q-w","errorCode":null,"errorMessage":"error downloading content from %q: %w","messagePattern":"error downloading content from %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/http.go","lineNumber":116,"sourceCode":"\t\talgorithm = hash.Algorithm\n\t}\n\thasher := algorithm.NewHasher()\n\twriter := io.MultiWriter(dest, hasher)\n\n\tswitch u.Scheme {\n\tcase \"gs\", \"s3\", \"azureblob\":\n\t\t// vfs resolves the bucket and signs the request with the ambient cloud credentials,\n\t\t// such as the instance identity.\n\t\tp, err := vfs.Context.BuildVfsPath(desturl)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"building path for %q: %w\", desturl, err)\n\t\t}\n\t\tcloudPath, ok := p.(vfs.WriterToWithContext)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"path type %T for %q does not implement WriteToWithContext\", p, desturl)\n\t\t}\n\t\tif _, err := cloudPath.WriteToWithContext(ctx, writer); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error downloading content from %q: %w\", desturl, err)\n\t\t}\n\tdefault:\n\t\treader, err := OpenURL(desturl)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer reader.Close()\n\n\t\tif _, err := io.Copy(writer, reader); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error downloading HTTP content from %q: %v\", desturl, err)\n\t\t}\n\t}\n\n\tactual := &hashing.Hash{\n\t\tAlgorithm: algorithm,\n\t\tHashValue: hasher.Sum(nil),\n\t}\n\tif hash != nil && !actual.Equal(hash) {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/http.go#L98-L134","documentation":"When the vfs path does support WriteToWithContext, the actual object download is performed by WriteToWithContext streaming into the writer. Any download failure (auth, network, object not found, aborted context) is wrapped with this message.","triggerScenarios":"cloudPath.WriteToWithContext(ctx, writer) returns an error while streaming from gs/s3/azureblob: 403/404 from the provider, network interruption, or context cancellation.","commonSituations":"Missing/deleted object in the bucket; instance role lacking s3:GetObject / storage.objects.get; expired ambient credentials; transient network failures mid-download.","solutions":["Inspect the wrapped error for the provider status code","Verify the object exists at the exact URL in the bucket","Grant the ambient identity GetObject/objects.get permission on the bucket","Retry if the cause was transient (kops retries on next apply)"],"exampleFix":"// before: 403 from provider\naws iam attach-role-policy --role-name nodes --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess\n// after: re-run kops update cluster","handlingStrategy":"retry","validationCode":"// Pre-flight: confirm the object exists and is readable\n_, err := s3Client.HeadObject(&s3.HeadObjectInput{Bucket: aws.String(b), Key: aws.String(k)})\nif err != nil { return fmt.Errorf(\"object missing or unreadable: %w\", err) }","typeGuard":null,"tryCatchPattern":"var lastErr error\nfor attempt := 0; attempt < 3; attempt++ {\n    _, err := fi.DownloadURL(ctx, assetURL, dest, nil)\n    if err == nil { break }\n    lastErr = err\n    if !strings.Contains(err.Error(), \"error downloading content\") { return err }\n    time.Sleep(backoff(attempt))\n}\nreturn lastErr","preventionTips":["Grant the node/instance role GetObject (or objects.get) on asset buckets","Verify object URLs exist in the bucket before referencing them","Use retry/backoff around downloads for transient network faults","Refresh ambient credentials (instance profiles) regularly"],"tags":["vfs","cloud-storage","network"],"backgroundTag":"object-download-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"}