GoogleContainerTools/skaffold · error
error closing GCS writer: %w
Error message
error closing GCS writer: %w
What it means
This error is returned by nativeBucketHandler.UploadObject when the GCS writer's Close() call fails after the file content has been copied. Closing a GCS writer is what actually flushes the data and finalizes the object upload; a failure here means the object was NOT successfully written despite io.Copy succeeding. It wraps the underlying error (network, permissions, or API failure) with %w for inspection via errors.Is/As.
Source
Thrown at pkg/skaffold/gcs/client/native.go:349
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
- Run `gcloud storage objects create`-equivalent check: verify the identity has storage.objects.create on the target bucket via `gsutil acl get` or IAM console
- Re-run the upload; Close failures from transient network issues are often resolved by retrying
- Check context cancellation upstream — ensure no timeout is killing the upload mid-flight
- If the bucket uses CMEK, verify the service account has roles/cloudkms.cryptoKeyEncrypterDecrypter
- Verify bucket retention/soft-delete policies are not rejecting the finalize operation
Example fix
// before
if err := wc.Close(); err != nil {
return fmt.Errorf("error closing GCS writer: %w", err)
}
// after
if err := wc.Close(); err != nil {
if ctx.Err() != nil {
return fmt.Errorf("error closing GCS writer (context canceled): %w", ctx.Err())
}
return fmt.Errorf("error closing GCS writer: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// validate bucket access before uploading
import "cloud.google.com/go/storage"
bkt := client.Bucket(bucketName)
if _, err := bkt.Attrs(ctx); err != nil {
return fmt.Errorf("bucket %s not accessible: %w", bucketName, err)
}
if _, err := os.Stat(localFile); err != nil {
return fmt.Errorf("content file missing: %w", err)
} Type guard
func isGCSError(err error) bool {
var se *googleapi.Error
return errors.As(err, &se)
} Try / catch
if err := handler.UploadObject(ctx, objName, f); err != nil {
var se *googleapi.Error
if errors.As(err, &se) && se.Code >= 500 {
// retry with backoff
}
if errors.Is(err, context.Canceled) {
// caller canceled; don't retry
}
return err
} Prevention
- Grant the service account storage.objects.create on the target bucket before uploads
- Avoid cancelling the context until after UploadObject returns
- Retry on transient (5xx) googleapi errors with exponential backoff
- For CMEK buckets, verify Cloud KMS encrypter/decrypter permissions
- Use resilient writers so Close() failures surface early with partial-upload context
When it happens
Trigger: Calling UploadObject (native GCS client path) where io.Copy succeeds but wc.Close() fails: network interruption during final flush, insufficient IAM permissions (storage.objects.create denied), bucket constraints (e.g. CMEK key unavailable, retention policy), or context cancellation right at the end of the upload.
Common situations: Uploading sources/artifacts to a GCS remote cache when credentials lack write access to the bucket; transient network drops mid-upload; service account key rotation revoking access; bucket using customer-managed encryption keys whose Cloud KMS permission was removed.
Related errors
- error copying file to GCS: %w
- uploading sources to google storage: %w
- failed to copy object to file: %v
- reading %q in embedded filesystem: %w
- failed to iterate objects: %v
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/261776a5cd966678.
Report an issue: GitHub.