{"record":{"id":"32feed11be550a91","repo":"RocketChat/Rocket.Chat","slug":"there-must-be-a-parent-room-to-create-a-discussion","errorCode":null,"errorMessage":"There must be a parent room to create a discussion.","messagePattern":"There must be a parent room to create a discussion\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/app/apps/server/bridges/rooms.ts","lineNumber":275,"sourceCode":"\n\tprotected async createDiscussion(\n\t\troom: IRoom,\n\t\tparentMessage: IMessage | undefined = undefined,\n\t\treply: string | undefined = '',\n\t\tmembers: Array<string> = [],\n\t\tappId: string,\n\t): Promise<string> {\n\t\tthis.orch.debugLog(`The App ${appId} is creating a new discussion.`, room);\n\n\t\tconst rcRoom = await this.orch.getConverters()?.get('rooms').convertAppRoom(room);\n\n\t\tlet rcMessage;\n\t\tif (parentMessage) {\n\t\t\trcMessage = await this.orch.getConverters()?.get('messages').convertAppMessage(parentMessage);\n\t\t}\n\n\t\tif (!rcRoom.prid || !(await Rooms.findOneById(rcRoom.prid))) {\n\t\t\tthrow new Error('There must be a parent room to create a discussion.');\n\t\t}\n\n\t\t// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.\n\t\tconst discussion = {\n\t\t\tprid: rcRoom.prid,\n\t\t\tt_name: rcRoom.fname as string,\n\t\t\tpmid: rcMessage ? rcMessage._id : undefined,\n\t\t\treply: reply && reply.trim() !== '' ? reply : undefined,\n\t\t\tusers: members.length > 0 ? members : [],\n\t\t};\n\n\t\tconst { rid } = await createDiscussion(room.creator.id, discussion);\n\n\t\treturn rid;\n\t}\n\n\tprotected getModerators(roomId: string, appId: string): Promise<IUser[]> {\n\t\tthis.orch.debugLog(`The App ${appId} is getting room moderators for room id: ${roomId}`);","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/app/apps/server/bridges/rooms.ts#L257-L293","documentation":"Thrown by the Apps Engine room bridge's createDiscussion when an app tries to create a discussion whose room has no parent room id (prid) or whose prid does not resolve to an existing room. Rocket.Chat discussions are threaded conversations that must be anchored to a parent channel/group, so the bridge verifies the parent exists in the database before delegating to createDiscussion.","triggerScenarios":"An app calls createDiscussion with an IRoom whose prid is undefined/empty, or with a prid that points to a room that was deleted or never existed. The check is `!rcRoom.prid || !(await Rooms.findOneById(rcRoom.prid))`.","commonSituations":"App author forgets to set room.prid; copies a room object from a channel read but strips prid; parent room is deleted in the window between the app reading it and creating the discussion; prid is mistyped or taken from the wrong field.","solutions":["Set room.prid to the _id of a real parent channel/group/private-team before calling createDiscussion.","Look up the parent room first (e.g. read.getRoomById) and validate it exists and the app can access it before creating the discussion.","Guard the call with a try/catch and surface a user-facing message instead of crashing the app flow when the parent is gone."],"exampleFix":"// before\nconst room: IRoom = { ...sharedRoomFields };\nawait modify.getCreator().startDiscussion(room, msg).setDisplayName('Thread').create();\n\n// after\nconst parent = await read.getRoomReader().getById(parentRoomId);\nif (!parent) {\n  // bail out gracefully\n  return;\n}\nconst room: IRoom = { ...sharedRoomFields, prid: parent.id } as any;\nawait modify.getCreator().startDiscussion(room, msg).setDisplayName('Thread').create();","handlingStrategy":"validation","validationCode":"const parent = await read.getRoomReader().getById(room.prid);\nif (!parent) {\n  throw new Error('Cannot create discussion: parent room does not exist');\n}","typeGuard":"function hasValidParent(room: IRoom): room is IRoom & { prid: string } {\n  return typeof room.prid === 'string' && room.prid.length > 0;\n}","tryCatchPattern":"try {\n  await modify.getCreator().startDiscussion(room, msg).create();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('parent room')) {\n    // parent missing or deleted — handle gracefully\n  } else {\n    throw err;\n  }\n}","preventionTips":["Always populate room.prid from a freshly-read parent room id.","Read the parent room immediately before creating the discussion to detect deletion.","Treat prid absence as a hard precondition in your app logic."],"tags":["apps-engine","rooms","discussion","validation","parent-room"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}