{"record":{"id":"03a7bbbb714449fd","repo":"RocketChat/Rocket.Chat","slug":"error-role-not-found","errorCode":"error-role-not-found","errorMessage":"Role not found","messagePattern":"Role not found","errorType":"exception","errorClass":"MeteorError","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/roles/updateRole.ts","lineNumber":58,"sourceCode":"\t} else {\n\t\troleData.scope = role.scope;\n\t}\n\n\tawait Roles.updateById(roleId, roleData.name, roleData.scope, roleData.description, roleData.mandatory2fa);\n\n\tvoid notifyOnRoleChangedById(roleId);\n\n\tif (options.broadcastUpdate) {\n\t\tvoid api.broadcast('user.roleUpdate', {\n\t\t\ttype: 'changed',\n\t\t\t_id: roleId,\n\t\t\tscope: roleData.scope,\n\t\t});\n\t}\n\n\tconst updatedRole = await Roles.findOneById(roleId);\n\tif (!updatedRole) {\n\t\tthrow new MeteorError('error-role-not-found', 'Role not found');\n\t}\n\n\treturn updatedRole;\n};\n","sourceCodeStart":40,"sourceCodeEnd":63,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/lib/roles/updateRole.ts#L40-L63","documentation":"Thrown by updateRole in updateRole.ts:58 after the update was written — when a follow-up findOneById(roleId) returns null. This indicates the role was deleted between the updateById and the re-fetch (a TOCTOU race), or updateById silently affected zero docs and the role never existed at re-read time. MeteorError code 'error-role-not-found'.","triggerScenarios":"Concurrent delete of the role during the update call; a DB inconsistency where updateById did not persist. The earlier findOneById check at line 19 already confirmed existence, so this is almost always a race or DB fault.","commonSituations":"Two admins editing/deleting the same role simultaneously; replication lag in a multi-node deployment; failed write that did not throw.","solutions":["Retry the read after a short delay; if still missing, treat as deleted.","Investigate concurrent deletes / replication health if it recurs.","Catch MeteorError 'error-role-not-found' and surface a stale-state message."],"exampleFix":"// before\nreturn await updateRole(roleId, roleData);\n\n// after\ntry { return await updateRole(roleId, roleData); }\ncatch (e) {\n  if (e.code === 'error-role-not-found') {\n    // role deleted mid-update; refresh list\n    return null;\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"// re-read right after update\nconst updated = await Roles.findOneById(roleId);\nif (!updated) throw new Error('role not persisted');","typeGuard":"const roleStillExists = async (id: string) => Boolean(await Roles.findOneById(id, { projection: { _id: 1 } }));","tryCatchPattern":"try { return await updateRole(roleId, roleData); }\ncatch (e) {\n  if (e?.code === 'error-role-not-found') return null; // deleted mid-update\n  throw e;\n}","preventionTips":["Avoid concurrent delete+update on the same role.","Investigate replication lag if this recurs."],"tags":["roles","race-condition","toctou","meteor-error"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}