{"record":{"id":"ee1dcb3ddcbc9717","repo":"Budibase/budibase","slug":"teams-create-conversation-failed-createresp-sta","errorCode":null,"errorMessage":"Teams create conversation failed (${createResp.status}): ${await createResp.text()}","messagePattern":"Teams create conversation failed \\((.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/escalation/notifications/ms-teams.ts","lineNumber":416,"sourceCode":"    channelData: { tenant: { id: msTenantId } },\n  }\n  console.log(\"sendMSTeamsNotification: creating conversation\", {\n    escalationId: contextDoc._id,\n    externalUserId,\n  })\n  const createResp = await fetch(\n    `${dmServiceUrl.replace(/\\/$/, \"\")}/v3/conversations`,\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${token}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify(createBody),\n    }\n  )\n  if (!createResp.ok) {\n    throw new Error(\n      `Teams create conversation failed (${createResp.status}): ${await createResp.text()}`\n    )\n  }\n  const conversation = (await createResp.json()) as {\n    id: string\n    serviceUrl?: string\n  }\n  const postServiceUrl = conversation.serviceUrl || DEFAULT_SERVICE_URL\n  console.log(\"sendMSTeamsNotification: conversation created\", {\n    conversationId: conversation.id,\n    serviceUrl: conversation.serviceUrl,\n    postServiceUrl,\n  })\n\n  await teamsPost(postServiceUrl, token, conversation.id, message)\n  console.log(\"sendMSTeamsNotification: message sent to user\", {\n    escalationId: notifDoc.escalationId,\n    externalUserId,","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/escalation/notifications/ms-teams.ts#L398-L434","documentation":"When sending a Teams DM escalation, sendMSTeamsNotification first creates a conversation between the bot and the recipient via POST {serviceUrl}/v3/conversations, passing the resolved externalUserId and tenant ID. If that create call returns non-ok, this error is thrown with the status and the Bot Framework error body, before any card is posted.","triggerScenarios":"The conversation-create POST returns non-2xx: 401 (bad bot token), 403 (bot cannot message that user — not installed/user blocked), 404 (externalUserId unknown to the tenant/bot), or the tenantId in channelData doesn't match the recipient.","commonSituations":"Stale identity link: user left the org or their Teams externalUserId changed; missing/wrong providerTenantId so the tenant in the create body is wrong; bot not deployed or messaging endpoint not configured for the tenant; default serviceUrl region mismatch with where the user's tenant lives.","solutions":["Re-resolve the recipient's identity link (chatIdentityLinks) to get a current externalUserId and serviceUrl; delete stale links for departed users.","Ensure providerTenantId (or the integration's tenant ID) matches the recipient's actual Azure AD tenant and is included in the create body's channelData.","Verify the bot is deployed (messagingEndpointUrl set) and installed in the recipient's tenant so it is permitted to create DM conversations.","Use the serviceUrl from the identity link rather than the default when operating across regions."],"exampleFix":"// before\nmembers: [{ id: staleExternalUserId }], tenantId: integration.msTenantId // 404\n// after\nconst link = await getChatIdentityLinkByGlobalUserId({ globalUserId, provider: \"msteams\" })\nmembers: [{ id: link.externalUserId }], tenantId: link.providerTenantId","handlingStrategy":"try-catch","validationCode":"if (!externalUserId || !providerTenantId) {\n  throw new Error(\"Cannot create Teams DM: missing externalUserId or tenantId\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sendMSTeamsNotification({ notifDoc, contextDoc })\n} catch (err) {\n  if (err.message.includes(\"create conversation failed\")) {\n    // 404: refresh identity link (externalUserId may be stale)\n    // 403: verify bot installed and not blocked by recipient\n  } else throw err\n}","preventionTips":["Re-validate identity links before sending; prune links for departed users","Ensure the bot is deployed (messagingEndpointUrl) and installed in the recipient's tenant","Send the correct providerTenantId in both the tenant field and channelData","Use the region-specific serviceUrl from the identity link when available"],"tags":["bot-framework","teams","http","identity"],"backgroundTag":"bot-conversation-create-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}