Skip to content

barman-cloud-backup Azure snapshot fails with strict deserializer in azure-mgmt-compute 38+ #1186

@jihokim-tibero

Description

@jihokim-tibero

Summary

barman-cloud-backup --cloud-provider azure-blob-storage --snapshot-instance ... fails immediately when run against a recent azure-mgmt-compute (38.0.0 verified) because barman passes the snapshot definition as a flat dict whose keys (incremental, creation_data) live in properties.* in the wire format. The SDK's strict deserializer rejects them at the root level.

Error

ERROR: Backup failed uploading data ((InvalidRequestContent) The request content was invalid
and could not be deserialized: 'Could not find member ''incremental'' on object of type
''ResourceDefinition''. Path 'incremental', line 1, position 45.'.)

Root cause

barman/cloud_providers/azure_blob_storage.py::_take_snapshot (current master too):

self.client.snapshots.begin_create_or_update(
    resource_group, snapshot_name,
    {
        "location": location,
        "incremental": True,
        "creation_data": {"create_option": "Copy", "source_uri": disk_id},
    },
)

azure-mgmt-compute's Snapshot._attribute_map:

Python attribute wire key
location location
incremental properties.incremental
creation_data properties.creationData

So incremental and creation_data must live under properties on the wire. The flat dict barman sends is neither a Snapshot model instance nor wire-format JSON. Older azure-mgmt-compute releases accepted the flat shape leniently; 38.0.0 (and likely some earlier versions of the strict-deserializer track) reject it.

Reproduction

Environment:

  • OS: Rocky Linux 9.6
  • Python: 3.12.12
  • PostgreSQL 16.9 / Patroni 4.0.5
  • barman / barman-cli / barman-cloud-backup: 3.18.0 (PGDG)
  • azure-core 1.41.0 / azure-identity 1.25.3 / azure-mgmt-core 1.6.0
  • azure-mgmt-compute 38.0.0 / azure-storage-blob 12.29.0

VM is in Azure (koreacentral region), single managed data disk attached, user-assigned managed identity with Storage Blob Data Contributor on the destination storage account.

Command (sanitized):

AZURE_STORAGE_AUTH_MECHANISM=managed-identity barman-cloud-backup \
  --cloud-provider azure-blob-storage \
  -h localhost -p 5432 -U postgres \
  --azure-subscription-id <sub-id> --azure-resource-group <rg> \
  --azure-credential managed-identity \
  --snapshot-instance <vm-name> --snapshot-disk <data-disk-name> \
  --name <backup-name> \
  https://<storage>.blob.core.windows.net/<container> <server-name>

The cli authenticates fine and reaches _take_snapshot before the failure surfaces.

Workaround

Pinning azure-mgmt-compute below the strict-deserializer release unblocks the backup:

pip install --user 'azure-mgmt-compute>=37.1.0,<38.0.0'

Verified: azure-mgmt-compute==37.2.0 runs the identical barman-cloud-backup command to a successful snapshot.

Suggested fix

Pass a Snapshot model object (or wire-format dict) instead of the flat dict:

from azure.mgmt.compute.models import Snapshot, CreationData, DiskCreateOption

self.client.snapshots.begin_create_or_update(
    resource_group,
    snapshot_name,
    Snapshot(
        location=location,
        incremental=True,
        creation_data=CreationData(
            create_option=DiskCreateOption.COPY,
            source_uri=disk_id,
        ),
    ),
)

This is unambiguous regardless of the SDK's deserializer mode.

In addition, the azure-snapshots extra in setup.py (line 55) has no upper bound:

"azure-snapshots": ["azure-identity", "azure-mgmt-compute"],

Consider adding azure-mgmt-compute<38.0.0 as a short-term safety pin (or, once the model-object fix above lands, a documented lower bound) so a fresh pip install doesn't auto-pick a version that breaks the snapshot path.

Affected versions

Confirmed on barman 3.18.0. master (as of 2026-05-17) still uses the same flat-dict pattern; no fix appears to be present yet.

References

Happy to send a PR if this analysis matches your intent for the fix shape — cc @didorgas @martinmarques.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions