{"record":{"id":"bc299a00fee43d4f","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-bc299a","errorCode":"error-invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"exception","errorClass":"MeteorError","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/rooms.ts","lineNumber":206,"sourceCode":"\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\tenum: [true],\n\t\t\t\t\t\tdescription: 'Indicates if the request was successful.',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trequired: ['success'],\n\t\t\t\tadditionalProperties: false,\n\t\t\t}),\n\t\t\t400: validateBadRequestErrorResponse,\n\t\t\t401: validateUnauthorizedErrorResponse,\n\t\t},\n\t},\n\tasync function action() {\n\t\tconst { roomId } = this.bodyParams;\n\n\t\tconst room = await Rooms.findOneById(roomId);\n\n\t\tif (!room) {\n\t\t\tthrow new MeteorError('error-invalid-room', 'Invalid room', {\n\t\t\t\tmethod: 'eraseRoom',\n\t\t\t});\n\t\t}\n\n\t\tif (room.teamMain) {\n\t\t\tthrow new Meteor.Error('error-cannot-delete-team-channel', 'Cannot delete a team channel', {\n\t\t\t\tmethod: 'eraseRoom',\n\t\t\t});\n\t\t}\n\n\t\tawait eraseRoom(room, this.user);\n\n\t\treturn API.v1.success();\n\t},\n);\n\nAPI.v1.get(\n\t'rooms.get',","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/rooms.ts#L188-L224","documentation":"Thrown by POST /api/v1/rooms.delete when Rooms.findOneById(roomId) returns null: the roomId in the body matches no room, typically because it was already deleted or is malformed. The error carries details.method 'eraseRoom' identifying the underlying operation. Deletion is not idempotent; a second delete of the same room fails here.","triggerScenarios":"POST rooms.delete with a roomId that was deleted in an earlier request (double-submit, retry after timeout, two admins racing); a copy-paste-mangled id; deleting from workspace A an id obtained from workspace B.","commonSituations":"Retry logic that re-sends deletion after a network timeout when the first attempt succeeded; cleanup scripts processing stale room lists; concurrent moderation actions; test teardown running twice.","solutions":["Confirm the room still exists with GET /api/v1/rooms.info?roomId=... before deleting","Treat this error as success in idempotent delete flows ('already gone')","Debounce or lock delete buttons and script steps to prevent double submission","Validate the id length/format before sending (Rocket.Chat ids are 17-char alphanumeric)"],"exampleFix":"// before\nawait sdk.post('rooms.delete', { roomId: staleId }); // already deleted -> error-invalid-room\n\n// after\ntry {\n  await sdk.get('rooms.info', { roomId: staleId });\n} catch {\n  return; // room already gone, nothing to delete\n}\nawait sdk.post('rooms.delete', { roomId: staleId });","handlingStrategy":"validation","validationCode":"try { await sdk.get('rooms.info', { roomId }); } catch { throw new Error(`room '${roomId}' does not exist`); }","typeGuard":null,"tryCatchPattern":"try {\n  await sdk.post('rooms.delete', { roomId });\n} catch (e: any) {\n  if (e?.response?.data?.errorType === 'error-invalid-room' && e?.response?.data?.details?.method === 'eraseRoom') {\n    return; // already deleted — idempotent success\n  }\n  throw e;\n}","preventionTips":["Treat double-delete as success in retry logic","Confirm existence before deleting when you need an audit decision point","Guard delete actions against double-submission in UIs"],"tags":["rooms","delete","idempotency","rest-api"],"backgroundTag":"room-not-found","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}