VictoriaMetrics/VictoriaMetrics · error
cannot perform server-side copying from %s to %s: both of th
Error message
cannot perform server-side copying from %s to %s: both of them must be AZBlob
What it means
CopyPart performs Azure Blob server-side (async) copying, which requires both the source and destination filesystems to be the azremote AZBlob FS implementation. The library type-asserts srcFS to *azremote.FS and throws this error when the source is a different storage backend (e.g. S3 or GCS), because StartCopyFromURL only works between Azure blobs.
Source
Thrown at lib/backup/azremote/azblob.go:212
return parts, nil
}
// DeletePart deletes part p from fs.
func (fs *FS) DeletePart(p common.Part) error {
return fs.delete(p.RemotePath(fs.Dir))
}
// RemoveEmptyDirs recursively removes empty dirs in fs.
func (fs *FS) RemoveEmptyDirs() error {
// Blob storage has no directories, so nothing to remove.
return nil
}
// CopyPart copies p from srcFS to fs.
func (fs *FS) CopyPart(srcFS common.OriginFS, p common.Part) error {
src, ok := srcFS.(*FS)
if !ok {
return fmt.Errorf("cannot perform server-side copying from %s to %s: both of them must be AZBlob", srcFS, fs)
}
sbc := src.client.NewBlobClient(p.RemotePath(src.Dir))
dbc := fs.clientForPart(p)
// In order to support copy of files larger than 256MB, we need to use the async copy
// Ref: https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url
_, err := dbc.StartCopyFromURL(fs.ctx, sbc.URL(), &blob.StartCopyFromURLOptions{})
if err != nil {
return fmt.Errorf("cannot start async copy %q from %s to %s: %w", p.Path, src, fs, err)
}
var copyStatus *blob.CopyStatusType
var copyStatusDescription *string
for {
r, err := dbc.GetProperties(fs.ctx, nil)
if err != nil {
return fmt.Errorf("failed to check copy status, cannot get properties of %q at %s: %w", p.Path, fs, err)View on GitHub (pinned to 5079fb58f1)
Solutions
- Ensure both srcFS and fs are created via the AZBlob (azremote) filesystem implementation.
- If the source cannot be Azure Blob, download the part from the source and upload it to the destination instead of server-side copy.
- Check your backup/storage configuration so both origin and destination point to the same Azure storage backend type.
Example fix
// before err := dstFS.CopyPart(s3FS, part) // s3FS is *s3remote.FS // after err := dstFS.CopyPart(azFS, part) // both must be *azremote.FS
Defensive patterns
Strategy: type-guard
Validate before calling
// before calling CopyPart
azFS, ok := srcFS.(*azremote.FS)
if !ok {
return fmt.Errorf("server-side copy unsupported for %T; use download+upload fallback", srcFS)
} Type guard
func asAZBlobFS(fs common.OriginFS) (*azremote.FS, bool) {
f, ok := fs.(*azremote.FS)
return f, ok
} Try / catch
if err := dstFS.CopyPart(srcFS, part); err != nil && strings.Contains(err.Error(), "both of them must be AZBlob") {
// fall back to DownloadPart(srcFS) + UploadPart(dstFS)
} Prevention
- Use the same storage backend type for origin and destination when relying on server-side copy
- Type-check FS implementations at pipeline construction time, not at copy time
- Implement a generic copy fallback (download+upload) for mixed-backend migrations
When it happens
Trigger: Calling CopyPart with a srcFS that is not the AZBlob FS wrapper, e.g. mixing S3-backed and AZBlob-backed origins in a backup/restore pipeline.
Common situations: Migration jobs between cloud providers where the source is S3/GCS and the destination is Azure; misconfigured backup destination so a non-Azure FS is passed; tests or custom OriginFS implementations that aren't backed by Azure Blob.
Related errors
- failed to create AZBlob service client: %w
- cannot start async copy %q from %s to %s: %w
- failed to check copy status, cannot get properties of %q at
- cannot set metadata for %q at %s: %w
- copy of %q from %s to %s failed: expected status %q, receive
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/8734d7b3250d6626.
Report an issue: GitHub.