Blob soft-delete vs versioning — recovering the wrong data
Undelete blob returns a version that does not match the expected data
Focused incident mode — strips away everything but this runbook.
Symptoms
- Undelete blob returns a version that does not match the expected data
- az storage blob list shows multiple versions of the same blob
- Restored blob has different content than the version deleted minutes ago
When both soft-delete and versioning are enabled, az storage blob undelete returns the soft-deleted marker, not necessarily the version you want. Always list versions explicitly before restoring.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Blob versions listed
az storage blob list --account-name <STORAGE-ACCOUNT> --container-name <CONTAINER> --include-v --prefix <BLOB-NAME> --query "[].{name:name,version:versionId}" -o tableSoft-delete and versioning status
az storage account blob-service-properties show --account-name <STORAGE-ACCOUNT> --query "{softDelete:deleteRetentionPolicy.enabled,versioning:isVersioningEnabled}" -o json
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- az storage blob undelete restores a different version than expected
- Blob has multiple versions after a delete/undelete cycle
Confirm before fixing
az storage blob list --account-name <STORAGE-ACCOUNT> --container-name <CONTAINER> --include-v --prefix <BLOB-NAME> --query "[].{name:name,version:versionId}" -o tableShow all versions
Fix
az storage blob copy start --account-name <STORAGE-ACCOUNT> --source-container <CONTAINER> --source-blob <BLOB-NAME> --source-version-id <DESIRED-VERSION> --destination-container <CONTAINER> --destination-blob <BLOB-NAME>-restoredCopy the correct version to a new blob
Expected: COPY IN PROGRESS
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
az storage account blob-service-properties show --account-name <STORAGE-ACCOUNT> --query "{softDelete:deleteRetentionPolicy.enabled,versioning:isVersioningEnabled}" -o jsonCheck the current configuration
az storage blob list --account-name <STORAGE-ACCOUNT> --container-name <CONTAINER> --include d --prefix <BLOB-NAME> --query "[].{name:name,deleted:deletedTime,version:versionId}" -o tableFind the soft-deleted blob
az storage blob list --account-name <STORAGE-ACCOUNT> --container-name <CONTAINER> --include-v --prefix <BLOB-NAME> --query "[].{name:name,version:versionId}" -o tableIdentify the correct version
az storage blob copy start --account-name <STORAGE-ACCOUNT> --source-container <CONTAINER> --source-blob <BLOB-NAME> --source-version-id <DESIRED-VERSION> --destination-container <CONTAINER> --destination-blob <BLOB-NAME>-restoredRestore the correct version explicitly
Prevention
- Choose one recovery mechanism: soft-delete OR versioning, not both for the same container.
- Set a short soft-delete retention (7 days) and monitor for accumulation.
- Use az storage blob list --include-v to verify versions before any restore.
- Test restore procedures regularly in a non-production container.
Related runbooks
Same stack, same failure family — worth a skim.
HTTP 403 Forbidden when accessing a blob URL
az storage account delete returns The resource is locked and cannot be deleted
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.