{"record":{"id":"9774aa6c371cba5a","repo":"Budibase/budibase","slug":"workspaceid-is-required-9774aa","errorCode":null,"errorMessage":"workspaceId is required","messagePattern":"workspaceId is required","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/deployments/shared.ts","lineNumber":27,"sourceCode":"/** Webhook URL path segment (ms-teams uses hyphen, provider value uses msteams) */\nexport const WEBHOOK_PATH_BY_PROVIDER: Record<AgentChannelProvider, string> = {\n  [AgentChannelProvider.MSTEAMS]: \"ms-teams\",\n  [AgentChannelProvider.SLACK]: \"slack\",\n}\n\nexport const buildWebhookUrl = async ({\n  provider,\n  agentId,\n  useProdWorkspaceId = false,\n}: {\n  provider: AgentChannelProvider\n  agentId: string\n  useProdWorkspaceId?: boolean\n}) => {\n  const platformUrl = await configs.getPlatformUrl({ tenantAware: true })\n  const workspaceId = context.getWorkspaceId()\n  if (!workspaceId) {\n    throw new HTTPError(\"workspaceId is required\", 400)\n  }\n  const targetWorkspaceId = useProdWorkspaceId\n    ? dbCore.getProdWorkspaceID(workspaceId)\n    : workspaceId\n  const pathSegment = WEBHOOK_PATH_BY_PROVIDER[provider]\n  return `${platformUrl.replace(/\\/$/, \"\")}/api/webhooks/${pathSegment}/${targetWorkspaceId}/${agentId}`\n}\n\nexport const buildProviderWebhookUrl = async (\n  provider: AgentChannelProvider,\n  agentId: string\n) =>\n  await buildWebhookUrl({\n    provider,\n    agentId,\n    useProdWorkspaceId: true,\n  })\n","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/deployments/shared.ts#L9-L45","documentation":"This HTTP 400 error is thrown by buildWebhookUrl in packages/server/src/sdk/workspace/ai/deployments/shared.ts when there is no workspace (app) ID available in the current request context while building a provider webhook URL. The webhook URL embeds the workspace ID as a path segment, so it is mandatory. getWorkspaceId() returns undefined when the code runs outside an app/workspace context (e.g. in the platform/global context or during a job without app context).","triggerScenarios":"Calling buildProviderWebhookUrl (for Slack, MS Teams, etc.) from a context where context.getWorkspaceId() returns undefined - e.g. building a webhook URL for an agent while operating at the platform/tenant level, in a background job without app context propagated, or before an app/workspace is opened in the request lifecycle.","commonSituations":"Running agent deployment code in a worker or script that did not switch into the app's database context; calling the deployment API without an app id in the request; unit/integration testing the function without initialising request context.","solutions":["Ensure the code that builds the webhook URL runs inside a workspace context (open the app's context, e.g. tenancy/doInWorkspace or equivalent before calling).","Pass the workspace/app ID through your request or job payload and set the context before invoking buildProviderWebhookUrl.","If testing, wrap the call in a test context helper that sets a workspace ID before asserting.","Check the deployment entry point (API route) is app-scoped, not a global/platform route."],"exampleFix":"// before\nconst url = await buildProviderWebhookUrl({ provider: \"slack\", agentId }) // runs with no workspace context\n// after\nawait withWorkspace(appId, async () => {\n  const url = await buildProviderWebhookUrl({ provider: \"slack\", agentId })\n})","handlingStrategy":"validation","validationCode":"const workspaceId = context.getWorkspaceId()\nif (!workspaceId) {\n  throw new Error(\"buildProviderWebhookUrl requires an active workspace context; open the app context first\")\n}","typeGuard":"const hasWorkspace = (): workspaceId is string => typeof context.getWorkspaceId() === \"string\" && context.getWorkspaceId() !== \"\"","tryCatchPattern":"try {\n  const url = await buildProviderWebhookUrl({ provider, agentId })\n} catch (e) {\n  if (e instanceof HTTPError && e.message === \"workspaceId is required\") {\n    // retry inside the app's workspace context\n  }\n  throw e\n}","preventionTips":["Always wrap deployment code in the app's workspace context helper (e.g. doInWorkspace) before calling shared SDK functions.","In background jobs, propagate the app ID in the job payload and enter its context at job start.","Add an assertion/log of getWorkspaceId() early in deployment entry points."],"tags":["context","webhook","workspace"],"backgroundTag":"missing-context-identifier","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}