weaviate/weaviate · error
close writer for file: %v
Error message
close writer for file: %v
What it means
With the GCS SDK, writer.Close() finalizes the resumable upload — this is where the object actually becomes visible, so most server-side rejections surface here rather than during Write. A Close error is wrapped as 'close writer for file: <objectName>' and means the object was NOT persisted despite Write returning nil.
Source
Thrown at modules/backup-gcs/client.go:330
func (g *gcsClient) PutObject(ctx context.Context, backupID, key, overrideBucket, overridePath string, byes []byte) error {
bucket, err := g.findBucket(ctx, overrideBucket)
if err != nil {
return errors.Wrap(err, "find bucket")
}
objectName := g.makeObjectName(overridePath, []string{backupID, key})
obj := bucket.Object(objectName)
writer := obj.NewWriter(ctx)
writer.ContentType = "application/octet-stream"
writer.Metadata = map[string]string{
"backup-id": backupID,
}
if _, err := writer.Write(byes); err != nil {
return errors.Wrapf(err, "write file: %v", objectName)
}
if err := writer.Close(); err != nil {
return errors.Wrapf(err, "close writer for file: %v", objectName)
}
metric, err := monitoring.GetMetrics().BackupStoreDataTransferred.GetMetricWithLabelValues("backup-gcs", "class")
if err == nil {
metric.Add(float64(len(byes)))
}
return nil
}
func (g *gcsClient) Initialize(ctx context.Context, backupID, overrideBucket, overridePath string) error {
if _, err := g.resolveBucketName(overrideBucket); err != nil {
return err
}
if g.config.SkipAccessCheck {
return nil
}View on GitHub (pinned to 75aa4b6d11)
Solutions
- Retry the backup operation — a failed Close means the object does not exist, so re-uploading is safe
- Verify the service account has storage.objects.create AND storage.objects.delete/update (Storage Object Admin covers it)
- Check quota/storage-class settings on the bucket and project
- Increase context timeout if the final flush of large objects exceeds the deadline; check the wrapped error for the HTTP status
Defensive patterns
Strategy: retry
Type guard
func uploadFinalized(err error) bool {
// nil error from Close means the object exists
return err == nil
} Try / catch
if err := module.Initialize(ctx, backupID, bucket, path); err != nil {
if strings.Contains(err.Error(), "close writer") {
// finalize failed: object not created; retry entire operation
}
}
// GCS SDK side: always check Close, never ignore it
w := obj.NewWriter(ctx)
w.Write(data)
if err := w.Close(); err != nil { return err } Prevention
- Always check writer.Close() — Write succeeding does not mean upload succeeded
- Grant full object create/delete/update permissions (Storage Object Admin)
- Monitor project storage quota before large backups
- Keep headroom in the context deadline for the final flush
When it happens
Trigger: writer.Close() fails: GCS returns 403 on finalize (permission checked late), quota exceeded, checksum validation failure, context deadline hit while flushing the final chunk, or 503 from GCS.
Common situations: Service account with create-but-no-finalize permissions; project nearing storage quota; short deadlines where the final flush of a large file exceeds the remaining time; transient GCS incidents during backup.
Related errors
- io.copy for gcs write %q: %w
- write file: %v
- find bucket: %w
- get next object: %w
- bucket must not be empty
AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04).
Data as JSON: /api/errors/dc16e6b9526cf533.
Report an issue: GitHub.