使用MS Teams Graph API $batch添加成员时遇PreconditionFailed错误求助
解决MS Teams Graph API $batch批量添加成员时的412 PreconditionFailed错误
问题场景
尝试通过Graph API的$batch接口批量向同一个Teams聊天(chat)添加成员,发送的请求负载如下:
{ "requests": [ { "id": "48374fe8-7d16-460c-9dff-e5091a134407", "method": "POST", "url": "chats/<GROUP-ID>/members", "headers": { "Content-Type": "application/json", "Cache-Control": "no-cache" }, "body": { "@odata.type": "#microsoft.graph.aadUserConversationMember", "user@odata.bind": "https://graph.microsoft.com/v1.0/users/<USER-ID>", "visibleHistoryStartDateTime": "0001-01-01T00:00:00Z", "roles": ["owner"] } }, { "id": "bbb5f15a-7d1d-4587-850b-d745359fced5", "method": "POST", "url": "chats/<GROUP-ID>/members", "headers": { "Content-Type": "application/json", "Cache-Control": "no-cache" }, "body": { "@odata.type": "#microsoft.graph.aadUserConversationMember", "user@odata.bind": "https://graph.microsoft.com/v1.0/users/<USER-ID>", "visibleHistoryStartDateTime": "0001-01-01T00:00:00Z", "roles": ["owner"] } } ] }
执行后收到412错误:
{ "id": "fce02ff7-7919-40f9-8a87-2073a87f0af0", "status": 412, "headers": { "Content-Type": "application/json" }, "body": { "error": { "code": "PreconditionFailed", "message": "PreconditionFailed", "innerError": { "message": "PreconditionFailed-ETag mismatch for thread store resource.", "code": "1", "innerError": {}, "date": "2023-02-22T04:54:26", "request-id": "da580345-eafc-4b2e-986b-70ca496679ae", "client-request-id": "70042dab-3d24-4644-99e2-13d4ef19042a" } } } }
对应的curl请求:
curl --location 'https://graph.microsoft.com/v1.0/$batch' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <TOKEN>' \ --header 'Cache-Control: max-age=0, must-revalidate' \ --data-raw '{"requests":[{"id":"48374fe8-7d16-460c-9dff-e5091a134407","method":"POST","url":"chats/<GROUP-ID>/members","headers":{"Content-Type":"application/json","Cache-Control":"no-cache"},"body":{"@odata.type":"#microsoft.graph.aadUserConversationMember","user@odata.bind":"https://graph.microsoft.com/v1.0/users/<USER-ID>","visibleHistoryStartDateTime":"0001-01-01T00:00:00Z","roles":["owner"]}}]}'
错误原因
Graph API的$batch默认会并行处理所有请求,当两个请求同时修改同一个chat资源(添加成员会更新chat的元数据,包括ETag)时,第一个请求完成后chat的ETag已经变更,第二个请求使用的还是旧的ETag,导致预条件校验失败,触发412错误。
解决方案
1. 使用dependsOn实现串行批量请求
在批量请求中通过dependsOn参数指定第二个请求依赖第一个请求完成,确保串行执行,避免ETag冲突。修改后的请求负载如下:
{ "requests": [ { "id": "48374fe8-7d16-460c-9dff-e5091a134407", "method": "POST", "url": "chats/<GROUP-ID>/members", "headers": { "Content-Type": "application/json", "Cache-Control": "no-cache" }, "body": { "@odata.type": "#microsoft.graph.aadUserConversationMember", "user@odata.bind": "https://graph.microsoft.com/v1.0/users/<USER-ID-1>", "visibleHistoryStartDateTime": "0001-01-01T00:00:00Z", "roles": ["owner"] } }, { "id": "bbb5f15a-7d1d-4587-850b-d745359fced5", "method": "POST", "url": "chats/<GROUP-ID>/members", "headers": { "Content-Type": "application/json", "Cache-Control": "no-cache" }, "body": { "@odata.type": "#microsoft.graph.aadUserConversationMember", "user@odata.bind": "https://graph.microsoft.com/v1.0/users/<USER-ID-2>", "visibleHistoryStartDateTime": "0001-01-01T00:00:00Z", "roles": ["owner"] }, "dependsOn": ["48374fe8-7d16-460c-9dff-e5091a134407"] } ] }
对应的curl请求:
curl --location 'https://graph.microsoft.com/v1.0/$batch' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <TOKEN>' \ --header 'Cache-Control: max-age=0, must-revalidate' \ --data-raw '{"requests":[{"id":"48374fe8-7d16-460c-9dff-e5091a134407","method":"POST","url":"chats/<GROUP-ID>/members","headers":{"Content-Type":"application/json","Cache-Control":"no-cache"},"body":{"@odata.type":"#microsoft.graph.aadUserConversationMember","user@odata.bind":"https://graph.microsoft.com/v1.0/users/<USER-ID-1>","visibleHistoryStartDateTime":"0001-01-01T00:00:00Z","roles":["owner"]}},{"id":"bbb5f15a-7d1d-4587-850b-d745359fced5","method":"POST","url":"chats/<GROUP-ID>/members","headers":{"Content-Type":"application/json","Cache-Control":"no-cache"},"body":{"@odata.type":"#microsoft.graph.aadUserConversationMember","user@odata.bind":"https://graph.microsoft.com/v1.0/users/<USER-ID-2>","visibleHistoryStartDateTime":"0001-01-01T00:00:00Z","roles":["owner"]},"dependsOn":["48374fe8-7d16-460c-9dff-e5091a134407"]}]}'
2. 分开发送单个请求
如果批量需求不强,可以直接分开发送两次独立的POST /chats/<GROUP-ID>/members请求,每次请求等待前一次完成后再发送,同样能避免ETag冲突。
注意事项
- 确保每个请求中的
<USER-ID>是不同的目标用户ID,避免重复添加同一个用户导致额外错误。 - 验证权限是否足够:需要
ChatMember.ReadWrite.All或Group.ReadWrite.All权限(根据chat类型不同)。
内容的提问来源于stack exchange,提问作者Parag Jadhav
相关产品推荐
相关产品推荐

