← Back to DevBytes

Troubleshooting Blob Storage: Common Issues and Solutions

Troubleshooting Blob Storage: Common Issues and Solutions

Blob storage is a foundational service in modern cloud applications, used for storing unstructured data such as images, videos, documents, backups, and logs. Whether you are using Azure Blob Storage, AWS S3, or Google Cloud Storage, developers frequently encounter similar categories of issues: authentication failures, network timeouts, missing blobs, CORS errors, and throttling. This tutorial walks through the most common Blob Storage problems, explains why they occur, and provides practical solutions with code examples you can apply immediately.

Why Troubleshooting Blob Storage Matters

Blob storage is often the silent backbone of an application. When it fails, the symptoms can be subtle: broken images on a website, failed file uploads, or delayed report generation. Because blob storage interacts with many layers of your stack — frontend, backend, CDN, and identity providers — pinpointing the root cause requires a systematic approach. Understanding common failure modes helps you reduce downtime, improve user experience, and avoid costly data loss.

1. Authentication and Authorization Errors

One of the most frequent issues developers face is the dreaded 403 Forbidden or AuthenticationFailed error. These occur when the credentials used to access the blob are invalid, expired, or lack the necessary permissions.

Common Causes

Solution: Generate a Valid SAS Token

When using SAS tokens, ensure the token has not expired and includes the necessary permissions (r for read, w for write, d for delete). Here is an example using the Azure Storage SDK for Python:

from datetime import datetime, timedelta
from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions

account_name = "mystorageaccount"
account_key = "your_account_key"
container_name = "mycontainer"
blob_name = "example.txt"

sas_token = generate_blob_sas(
    account_name=account_name,
    container_name=container_name,
    blob_name=blob_name,
    account_key=account_key,
    permission=BlobSasPermissions(read=True),
    expiry=datetime.utcnow() + timedelta(hours=1),
    start=datetime.utcnow() - timedelta(minutes=5)  # allow for clock skew
)

blob_url = f"https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}?{sas_token}"
print(blob_url)

Notice the start time is set slightly in the past. This accounts for clock skew between the client machine and the storage service, which is a surprisingly common cause of authentication failures.

Using Managed Identity Instead of Keys

For production workloads, prefer Managed Identity over account keys. This eliminates the risk of leaked credentials:

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
    account_url="https://mystorageaccount.blob.core.windows.net",
    credential=credential
)

blob_client = blob_service_client.get_blob_client(
    container="mycontainer",
    blob="example.txt"
)

with open("example.txt", "rb") as data:
    blob_client.upload_blob(data)
print("Upload successful")

Ensure the Managed Identity has the Storage Blob Data Contributor role assigned at the storage account, container, or blob level.

2. Blob Not Found (404) Errors

A 404 Not Found error is straightforward but can be tricky to debug when you are certain the blob exists. The issue often comes down to case sensitivity, container naming, or soft-deleted blobs.

Common Causes

Solution: Verify Blob Existence and Handle Soft Deletes

from azure.storage.blob import BlobServiceClient
from azure.core.exceptions import ResourceNotFoundError

blob_service_client = BlobServiceClient.from_connection_string(conn_str)
blob_client = blob_service_client.get_blob_client("mycontainer", "Image.PNG")

try:
    props = blob_client.get_blob_properties()
    print(f"Blob exists. Size: {props.size} bytes")
except ResourceNotFoundError:
    print("Blob not found. Checking for soft-deleted blobs...")
    
    # List soft-deleted blobs
    container_client = blob_service_client.get_container_client("mycontainer")
    deleted_blobs = container_client.list_blobs(include_deleted=True)
    for b in deleted_blobs:
        if b.name == "Image.PNG" and b.deleted:
            print(f"Found soft-deleted blob. Restoring...")
            blob_client.undelete_blob()
            print("Blob restored successfully.")
            break

Enabling soft delete on your storage account gives you a safety net for accidental deletions. You can configure the retention period from 1 to 365 days.

3. Connection Timeouts and Network Issues

Timeouts can occur during large uploads, downloads, or when the network between your application and the storage service is unreliable. The default timeout in most SDKs is 30 seconds, which may be insufficient for large files.

Solution: Configure Timeouts and Use Retry Policies

from azure.storage.blob import BlobServiceClient, BlobClient
from azure.core.pipeline.policies import RetryPolicy

custom_retry = RetryPolicy(
    total_retries=5,
    backoff_factor=2,
    retry_total=5
)

blob_service_client = BlobServiceClient.from_connection_string(
    conn_str,
    retry_policy=custom_retry
)

blob_client = blob_service_client.get_blob_client("mycontainer", "large-file.zip")

with open("large-file.zip", "rb") as data:
    blob_client.upload_blob(
        data,
        timeout=300,  # 5 minute timeout
        overwrite=True
    )
print("Large file uploaded successfully.")

Using Block Blobs for Large Files

For files larger than a few hundred megabytes, use block-based uploads. This allows parallel uploads and resumable transfers:

from azure.storage.blob import BlobClient
import os

blob_client = BlobClient.from_blob_url(blob_url_with_sas)

file_path = "large-video.mp4"
chunk_size = 4 * 1024 * 1024  # 4 MB chunks

with open(file_path, "rb") as f:
    block_ids = []
    index = 0
    while True:
        chunk = f.read(chunk_size)
        if not chunk:
            break
        block_id = f"{index:06d}"
        blob_client.stage_block(block_id, chunk)
        block_ids.append(block_id)
        index += 1
        print(f"Uploaded block {index}")

blob_client.commit_block_list(block_ids)
print(f"Upload complete. Total blocks: {index}")

If a chunk fails, you only need to re-upload that specific block, not the entire file.

4. CORS Errors from Browser Applications

When accessing blob storage directly from a browser (e.g., uploading files from a React or Vue frontend), you may encounter CORS errors in the browser console. This happens because the storage account has not been configured to allow cross-origin requests from your domain.

Solution: Configure CORS Rules

You can configure CORS rules through the Azure Portal, Azure CLI, or programmatically:

from azure.storage.blob import BlobServiceClient

blob_service_client = BlobServiceClient.from_connection_string(conn_str)

cors_rules = [{
    "allowed_origins": ["https://myapp.example.com", "http://localhost:3000"],
    "allowed_methods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "allowed_headers": ["*"],
    "exposed_headers": ["ETag", "Content-Length"],
    "max_age_in_seconds": 3600
}]

service_properties = blob_service_client.set_service_properties(cors=cors_rules)
print("CORS rules configured successfully.")

Key points to remember:

5. Throttling (429 Too Many Requests)

Storage accounts have scalability targets. For standard general-purpose accounts, the target is up to 20,000 requests per second. When you exceed this limit, the service returns a 429 status code. This is common in batch processing, log ingestion, or high-traffic web applications.

Common Causes

Solution: Implement Exponential Backoff and Partitioning

import time
from azure.storage.blob import BlobServiceClient
from azure.core.exceptions import ResourceExistsError

blob_service_client = BlobServiceClient.from_connection_string(conn_str)

def upload_with_retry(container_name, blob_name, data, max_retries=5):
    blob_client = blob_service_client.get_blob_client(container_name, blob_name)
    
    for attempt in range(max_retries):
        try:
            blob_client.upload_blob(data, overwrite=True)
            print(f"Upload successful on attempt {attempt + 1}")
            return True
        except Exception as e:
            if "429" in str(e) or "ServerBusy" in str(e):
                wait_time = (2 ** attempt) + 0.5  # exponential backoff with jitter
                print(f"Throttled. Retrying in {wait_time:.1f}s (attempt {attempt + 1})")
                time.sleep(wait_time)
            else:
                raise e
    raise Exception(f"Failed after {max_retries} retries")

upload_with_retry("mycontainer", "data.json", b'{"key": "value"}')

For high-throughput scenarios, distribute blobs across multiple containers or use a naming convention that spreads them across different partitions. Avoid naming all blobs with the same prefix (e.g., timestamps like 2024-01-01-log-001), as this can cause hot partition issues.

6. Accidental Overwrites and Data Corruption

When multiple processes write to the same blob simultaneously, or when a bug overwrites data unexpectedly, you can lose critical information. This is especially dangerous in shared containers.

Solution: Use Lease and Versioning

A lease provides exclusive write access to a blob for a specified duration:

from azure.storage.blob import BlobClient, LeaseClient

blob_client = BlobClient.from_blob_url(blob_url_with_sas)
lease_client = LeaseClient(blob_client)

# Acquire a lease for 60 seconds
lease = lease_client.acquire(lease_duration=60)
print(f"Lease acquired: {lease}")

try:
    # Only the lease holder can write to this blob
    blob_client.upload_blob(b"new data", lease=lease)
    print("Data written with lease protection.")
finally:
    lease_client.release()
    print("Lease released.")

Additionally, enable blob versioning on your storage account. This automatically preserves previous versions of a blob every time it is modified, giving you point-in-time recovery without any code changes.

Best Practices for Blob Storage Reliability

Conclusion

Troubleshooting Blob Storage issues requires a combination of understanding the underlying service mechanics and implementing defensive coding practices. By addressing authentication errors proactively, handling 404s with soft-delete recovery, configuring proper timeouts and retry policies, resolving CORS configuration, and guarding against throttling and data corruption, you can build robust applications that handle storage operations reliably. The key is to never assume storage operations will always succeed — always implement error handling, retries, and monitoring. With the strategies and code examples in this tutorial, you are well-equipped to diagnose and resolve the most common Blob Storage problems in your applications.

— Ad —

Google AdSense will appear here after approval

← Back to all articles