{"record":{"id":"4af2de0e205fb7c9","repo":"Budibase/budibase","slug":"preview-mode-requires-a-development-workspace","errorCode":null,"errorMessage":"Preview mode requires a development workspace","messagePattern":"Preview mode requires a development workspace","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/chatConversations.ts","lineNumber":395,"sourceCode":"  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\n  const agentId = chat.agentId\n  if (!agentId) {\n    throw new HTTPError(\"agentId is required\", 400)\n  }","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/chatConversations.ts#L377-L413","documentation":"Preview chat streaming is restricted to development (draft) workspaces. isDevWorkspaceID(workspaceId) rejects requests against a published/deployed workspace id, throwing HTTP 400 'Preview mode requires a development workspace'.","triggerScenarios":"Sending isPreview: true to the chat stream endpoint while the resolved workspaceId is a published app id (not the dev/draft id).","commonSituations":"Client using the production appId with preview flags; testing after the app was published and the dev id changed; hard-coded app ids in scripts.","solutions":["Use the development/draft workspace id (appDevId) in the request","Obtain the dev app id from the builder UI or the app metadata API","Point scripts at the dev workspace rather than the published one"],"exampleFix":"// before\nheaders: { 'x-budibase-app-id': publishedAppId }\n// after\nheaders: { 'x-budibase-app-id': devAppId }","handlingStrategy":"validation","validationCode":"if (!isDevId(appId)) {\n  throw new Error(\"Preview chat requires the development (draft) app id\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  await streamChat(body)\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes(\"development workspace\")) {\n    // swap in the dev app id and retry\n  }\n}","preventionTips":["Store and use the dev app id separately from the published app id","Re-fetch app metadata after publishing, since ids/environments differ","Never hard-code a published app id for preview flows"],"tags":["validation","http-400","workspace-context"],"backgroundTag":"wrong-workspace-environment","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}