{"record":{"id":"bcbd4b189c67a7dd","repo":"Budibase/budibase","slug":"forbidden","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":"HTTPError","httpStatus":403,"severity":"error","filePath":"packages/server/src/api/controllers/ai/chatConversations.ts","lineNumber":391,"sourceCode":"  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\n  let user = ctx.user\n  if (chat.previewRoleId) {\n    const previewRole = await roles.getRole(chat.previewRoleId)\n    if (!previewRole?._id) {\n      throw new HTTPError(\"Preview role not found\", 400)\n    }\n    user = {\n      ...ctx.user,\n      roleId: previewRole._id,\n    }\n  }\n","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/chatConversations.ts#L373-L409","documentation":"Even in preview mode, only workspace admins or builders may stream agent chats. The SDK check users.isAdminOrBuilder(ctx.user, workspaceId) gates the endpoint; regular app users receive HTTP 403 'Forbidden'.","triggerScenarios":"An authenticated app-end user (non-builder, non-admin role) POSTs to the preview chat stream endpoint with isPreview: true.","commonSituations":"Testing agent chat as a normal app user; role downgrades after re-login; previewRoleId spoofing attempts by non-privileged users.","solutions":["Log in as a builder or workspace admin to use preview chat","Grant the user builder/admin permissions in the workspace if legitimately needed","Use the non-preview (production) chat path for end users, if available"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const canPreview = [\"ADMIN\", \"BUILDER\"].includes(user.roleId)\nif (!canPreview) throw new Error(\"Builder or admin role required for preview chat\")","typeGuard":null,"tryCatchPattern":"try {\n  await streamChat(body)\n} catch (e) {\n  if (e.status === 403) {\n    // show a 'builder/admin only' message instead of retrying\n  }\n}","preventionTips":["Gate preview chat UI behind builder/admin role checks","Don't attempt preview chat with end-user tokens","Handle 403 distinctly from 400 client errors"],"tags":["auth","permissions","http-403"],"backgroundTag":"insufficient-permissions","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}