{"record":{"id":"e476f18c9ab6bcf5","repo":"Budibase/budibase","slug":"teams-integration-must-be-provisioned-before-downl","errorCode":null,"errorMessage":"Teams integration must be provisioned before downloading the app package","messagePattern":"Teams integration must be provisioned before downloading the app package","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/agents.ts","lineNumber":275,"sourceCode":"    .replace(/[^a-z0-9._-]+/g, \"-\")\n    .replace(/^-+|-+$/g, \"\")\n  return safe || \"agent\"\n}\n\nconst toSafeTeamsPackageName = (agent: Agent) =>\n  `budibase-teams-${toSafeFilenameSegment(agent.name)}-package.zip`\n\nconst allocateMSTeamsAppPackageVersion = async (agentId: string) => {\n  for (\n    let attempt = 0;\n    attempt < TEAMS_APP_PACKAGE_VERSION_RETRIES;\n    attempt++\n  ) {\n    const agent = await sdk.ai.agents.getOrThrow(agentId)\n    const messagingEndpointUrl =\n      agent.MSTeamsIntegration?.messagingEndpointUrl?.trim()\n    if (!messagingEndpointUrl) {\n      throw new HTTPError(\n        \"Teams integration must be provisioned before downloading the app package\",\n        400\n      )\n    }\n\n    sdk.ai.deployments.MSTeams.validateMSTeamsIntegration(agent)\n\n    const currentVersion =\n      agent.MSTeamsIntegration?.appPackageVersion ||\n      INITIAL_TEAMS_APP_PACKAGE_VERSION\n    const appPackageVersion = semver.inc(currentVersion, \"patch\")\n    if (!appPackageVersion) {\n      throw new HTTPError(\"Invalid Teams app package version\", 500)\n    }\n\n    try {\n      const updatedAgent = await sdk.ai.agents.update({\n        ...agent,","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/agents.ts#L257-L293","documentation":"Thrown by allocateMSTeamsAppPackageVersion when a Teams app package is requested for an agent whose MSTeamsIntegration has no messagingEndpointUrl (missing, empty, or whitespace-only). The package download depends on a provisioned Teams integration that exposes the messaging endpoint; without it the library refuses with a 400.","triggerScenarios":"Downloading the Teams app package for an agent before the Microsoft Teams integration was provisioned, after provisioning failed partway (URL never saved), or after the URL was cleared/blanked while the integration object still exists. The check retries via getOrThrow until attempts are exhausted but never succeeds without a URL.","commonSituations":"Admins clicking 'Download app package' in the builder before finishing Teams setup; Teams provisioning webhook failing silently so messagingEndpointUrl stays empty; API-driven flows that create the integration shell but skip the provisioning step; environment/region changes that invalidate a previously provisioned endpoint.","solutions":["Complete the Microsoft Teams integration provisioning so agent.MSTeamsIntegration.messagingEndpointUrl is set","Verify the agent config: agent.MSTeamsIntegration must exist with a non-empty trimmed messagingEndpointUrl","Re-run the Teams setup/provisioning step if a previous attempt failed, then retry the download","If the endpoint URL was cleared, restore it via the agent update API before downloading the package"],"exampleFix":"// before\nGET /api/ai/agents/agent123/teams/app-package // integration not provisioned\n// after\n// 1. provision Teams integration first\nawait sdk.ai.agents.updateOperation(agentId, opId, {\n  MSTeamsIntegration: { messagingEndpointUrl: \"https://example.com/teams/msg\" }\n})\n// 2. then download the package\nGET /api/ai/agents/agent123/teams/app-package","handlingStrategy":"validation","validationCode":"function canDownloadTeamsPackage(agent) {\n  return Boolean(agent?.MSTeamsIntegration?.messagingEndpointUrl?.trim())\n}\nif (!canDownloadTeamsPackage(agent)) {\n  throw new Error(\"Provision the Teams integration before downloading the app package\")\n}","typeGuard":"function isTeamsProvisioned(agent) {\n  return typeof agent?.MSTeamsIntegration?.messagingEndpointUrl === \"string\" &&\n    agent.MSTeamsIntegration.messagingEndpointUrl.trim().length > 0\n}","tryCatchPattern":"try {\n  const pkg = await downloadMSTeamsAppPackage(agentId)\n} catch (err) {\n  if (err.status === 400 && /Teams integration must be provisioned/.test(err.message)) {\n    await provisionMSTeamsIntegration(agentId)\n    return downloadMSTeamsAppPackage(agentId)\n  }\n  throw err\n}","preventionTips":["Gate the 'Download app package' UI action on the integration being fully provisioned","Verify provisioning webhooks actually persisted messagingEndpointUrl before exposing downloads","Re-run provisioning when the endpoint URL is empty or blanked","Monitor Teams provisioning failures so agents never sit in a half-configured state"],"tags":["validation","http-400","ms-teams","integration-provisioning"],"backgroundTag":"integration-not-provisioned","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}