使用Azure Python SDK解除Blob租约时遇MissingRequiredHeader错误
Azure Blob租约解除时MissingRequiredHeader错误排查
问题复现
执行以下代码尝试解除Blob租约时,收到HttpResponseError: (MissingRequiredHeader) An HTTP header that's mandatory for this request is not specified.错误:
from azure.identity import DefaultAzureCredential, AzureCliCredential, ChainedTokenCredential, ClientSecretCredential from azure.storage.blob import BlobServiceClient, BlobClient, BlobLeaseClient import datetime dbutils.widgets.text('client_id', '') dbutils.widgets.text('tenant_id', '') dbutils.widgets.text('lake_secret', '') client_id = dbutils.widgets.get('client_id') tenant_id = dbutils.widgets.get('tenant_id') lake_secret = dbutils.widgets.get('lake_secret') azure_secret_credentials = ClientSecretCredential(client_secret=lake_secret, client_id=client_id, tenant_id=tenant_id) credential = ChainedTokenCredential(AzureCliCredential(), azure_secret_credentials) token = credential.get_token('.default') api_version = '2023-08-03' request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') headers = { 'x-ms-date' : request_time, 'x-ms-version' : api_version, 'Authorization' : azure_secret_credentials.get_token('https://storage.azure.com/.default'), "x-ms-lease-action": "break", "x-ms-version": "2021-12-02", "Accept": "application/xml" } account_url = "<url>" bsc = BlobServiceClient(account_url=account_url, credential=credential) bc = bsc.get_blob_client('lake', '<path>') blc = BlobLeaseClient(bc) blc.break_lease(0, headers=headers)
错误原因及解决思路
1. 手动构造请求头干扰SDK逻辑
Azure Storage Python SDK会自动处理Authorization、x-ms-date、x-ms-version等核心请求头,手动传入自定义headers会覆盖或冲突SDK的默认处理,导致头部格式错误或缺失。
2. Authorization头格式错误
直接传入token对象而非符合要求的Bearer <token值>格式,正确格式需要提取token的token属性并拼接前缀。
3. x-ms-version重复定义
headers中同时设置两个不同的API版本(2023-08-03和2021-12-02),导致请求头部冲突。
修正后的代码
移除手动构造的headers,直接调用SDK原生方法即可:
from azure.identity import ClientSecretCredential, ChainedTokenCredential, AzureCliCredential from azure.storage.blob import BlobServiceClient, BlobLeaseClient dbutils.widgets.text('client_id', '') dbutils.widgets.text('tenant_id', '') dbutils.widgets.text('lake_secret', '') client_id = dbutils.widgets.get('client_id') tenant_id = dbutils.widgets.get('tenant_id') lake_secret = dbutils.widgets.get('lake_secret') azure_secret_credentials = ClientSecretCredential(client_secret=lake_secret, client_id=client_id, tenant_id=tenant_id) credential = ChainedTokenCredential(AzureCliCredential(), azure_secret_credentials) account_url = "<url>" # SDK自动处理认证和请求头 bsc = BlobServiceClient(account_url=account_url, credential=credential) bc = bsc.get_blob_client(container='lake', blob='<path>') blc = BlobLeaseClient(blob_client=bc) # 直接调用break_lease,无需自定义headers blc.break_lease(lease_break_period=0)
额外排查点
- 确认
<path>是Blob的完整路径,无拼写错误 - 检查服务主体是否拥有Storage Blob Data Contributor或更高权限
- 可通过
blc.get_lease_state()提前确认Blob是否存在活跃租约
内容的提问来源于stack exchange,提问作者rmesteves
相关产品推荐
相关产品推荐

