{"record":{"id":"4cdf62bb3aa7cc09","repo":"Budibase/budibase","slug":"workspace-context-is-required","errorCode":null,"errorMessage":"Workspace context is required","messagePattern":"Workspace context is required","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/chatConversations.ts","lineNumber":379,"sourceCode":"\n  if (agentId) {\n    chat.agentId = agentId\n  }\n  if (chatConversationId && chatConversationId !== \"new\") {\n    chat._id = chatConversationId\n  }\n}\n\nconst resolveChatStreamRequest = async (\n  ctx: UserCtx<ChatAgentRequest, void>\n): Promise<ResolvedChatStreamRequest> => {\n  const chat = ctx.request.body\n  const userId = getGlobalUserId(ctx)\n  applyChatStreamPathParams(chat, ctx.params)\n\n  const workspaceId = context.getWorkspaceId()\n  if (!workspaceId) {\n    throw new HTTPError(\"Workspace context is required\", 400)\n  }\n  const isBuilderOrAdmin = usersSdk.users.isAdminOrBuilder(\n    ctx.user,\n    workspaceId\n  )\n\n  if (chat.isPreview !== true) {\n    throw new HTTPError(\"Preview mode is required\", 400)\n  }\n\n  if (!isBuilderOrAdmin) {\n    throw new HTTPError(\"Forbidden\", 403)\n  }\n\n  if (!isDevWorkspaceID(workspaceId)) {\n    throw new HTTPError(\"Preview mode requires a development workspace\", 400)\n  }\n","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/chatConversations.ts#L361-L397","documentation":"Chat streaming requests must run inside a workspace (app) context. context.getWorkspaceId() derives this from the request (headers, subdomain, or URL). When absent — e.g. calls outside an app context — the server throws HTTP 400 'Workspace context is required'.","triggerScenarios":"Calling the chat stream endpoint without the workspace-scoped URL/headers (e.g. hitting the worker/global API directly, or missing appId header).","commonSituations":"Scripted API calls omitting the 'x-budibase-app-id' header; using the global/worker port instead of the app API; reverse proxy stripping headers.","solutions":["Include the workspace/app id in the request (x-budibase-app-id header or app-scoped URL)","Call the app API endpoint rather than the global/worker endpoint","Verify proxies don't strip Budibase context headers"],"exampleFix":"// before\nfetch('http://localhost:4002/api/ai/chat/agent_1/stream', {...})\n// after\nfetch('http://localhost:4001/api/ai/chat/agent_1/stream', {\n  headers: { 'x-budibase-app-id': appId, ...auth }\n})","handlingStrategy":"validation","validationCode":"if (!appId) {\n  throw new Error(\"Workspace/app id is required for chat streaming\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  await streamChat(body)\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes(\"Workspace context is required\")) {\n    // add the x-budibase-app-id header and retry\n  }\n}","preventionTips":["Always send x-budibase-app-id on AI endpoints","Call the app API (server), not the worker/global API, for chat","Check proxy configs don't strip Budibase headers"],"tags":["validation","http-400","workspace-context"],"backgroundTag":"missing-workspace-context","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}