GoogleContainerTools/skaffold · error
error copying file to GCS: %w
Error message
error copying file to GCS: %w
What it means
UploadObject wraps io.Copy failures while streaming a local file into a GCS object writer. It means the upload data transfer failed — network interruption, context cancellation, or an API error during resumable upload. Note the writer's Close error is reported separately, so this is specifically the copy/streaming phase.
Source
Thrown at pkg/skaffold/gcs/client/native.go:346
defer reader.Close()
file, err := os.Create(localPath)
if err != nil {
return fmt.Errorf("failed to create file: %v", err)
}
defer file.Close()
if _, err := io.Copy(file, reader); err != nil {
return fmt.Errorf("failed to copy object to file: %v", err)
}
return nil
}
func (nb nativeBucketHandler) UploadObject(ctx context.Context, objName string, content *os.File) error {
wc := nb.bucket.Object(objName).NewWriter(ctx)
if _, err := io.Copy(wc, content); err != nil {
return fmt.Errorf("error copying file to GCS: %w", err)
}
if err := wc.Close(); err != nil {
return fmt.Errorf("error closing GCS writer: %w", err)
}
return nil
}
func (nb nativeBucketHandler) Close() {
nb.storageClient.Close()
}
View on GitHub (pinned to a1189de023)
Solutions
- Retry the upload (GCS resumable uploads are designed to be retried from scratch via a new NewWriter call)
- Increase the context deadline to cover the expected upload duration
- Check network/proxy stability and firewall rules for storage.googleapis.com
- For large files, verify disk read speed and that the source file is not being modified during upload
Example fix
// before
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := n.UploadFile(ctx, bigFile, "gs://bucket/artifacts/app.tar.gz"); err != nil { return err } // timeout mid-copy
// after
uctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
defer cancel()
err := n.UploadFile(uctx, bigFile, "gs://bucket/artifacts/app.tar.gz")
if err != nil && isRetryable(err) {
err = n.UploadFile(uctx, bigFile, "gs://bucket/artifacts/app.tar.gz")
} Defensive patterns
Strategy: retry
Validate before calling
func hasDiskSpaceFor(src string) error {
fi, err := os.Stat(src)
if err != nil { return err }
if fi.Size() > 5<<30 { // large files: pre-check via resumable session is done by the lib
log.Printf("uploading large file %s (%d bytes)", src, fi.Size())
}
return nil
}
// also ensure the context deadline comfortably exceeds expected upload time Try / catch
err := n.UploadFile(ctx, src, dst)
if err != nil && strings.Contains(err.Error(), "error copying file to GCS") {
if isRetryable(err) { // 429/5xx/network
return retryBackoff(3, time.Second, func() error {
return n.UploadFile(ctx, src, dst)
})
}
return err
} Prevention
- Size the context timeout to the file size and link speed
- Retry idempotent uploads on transient/network errors
- Keep long-lived connections to storage.googleapis.com unfiltered by proxies
- Do not modify the source file while it is being uploaded
When it happens
Trigger: Calling UploadFile (which delegates to UploadObject) when the connection to GCS drops or the context is cancelled while the file is streaming, or the underlying writer encounters an API error mid-upload.
Common situations: Uploading large artifacts from CI with unstable networking; context timeout shorter than upload time on slow links; GCS returning 429/5xx mid-stream under heavy load; proxy killing long-lived connections.
Related errors
- error closing GCS writer: %w
- failed to copy object to file: %v
- uploading sources to google storage: %w
- failed to iterate objects: %v
- failed to read object: %v
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/17bf1b05434e5f4b.
Report an issue: GitHub.