{"record":{"id":"f0bbb9da734d58d6","repo":"danny-avila/LibreChat","slug":"role-accessroleid-not-found","errorCode":null,"errorMessage":"Role ${accessRoleId} not found","messagePattern":"Role (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/server/services/PermissionService.js","lineNumber":108,"sourceCode":"    } else if (\n      principalType &&\n      principalType !== PrincipalType.PUBLIC &&\n      !mongoose.Types.ObjectId.isValid(principalId)\n    ) {\n      // User and Group IDs must be valid ObjectIds\n      throw new Error(`Invalid principal ID: ${principalId}`);\n    }\n\n    if (!resourceId || !mongoose.Types.ObjectId.isValid(resourceId)) {\n      throw new Error(`Invalid resource ID: ${resourceId}`);\n    }\n\n    validateResourceType(resourceType);\n\n    // Get the role to determine permission bits\n    const role = await db.findRoleByIdentifier(accessRoleId);\n    if (!role) {\n      throw new Error(`Role ${accessRoleId} not found`);\n    }\n\n    // Ensure the role is for the correct resource type\n    if (role.resourceType !== resourceType) {\n      throw new Error(\n        `Role ${accessRoleId} is for ${role.resourceType} resources, not ${resourceType}`,\n      );\n    }\n    return await db.grantPermission(\n      principalType,\n      principalId,\n      resourceType,\n      resourceId,\n      role.permBits,\n      grantedBy,\n      session,\n      role._id,\n    );","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/PermissionService.js#L90-L126","documentation":"Thrown by PermissionService.grantPermission after db.findRoleByIdentifier(accessRoleId) returns null. The access role identifier passed in does not resolve to any document in the roles collection, so the service cannot determine the permBits to grant. Roles are expected to be referenced by a known identifier (e.g. AccessRoleIds.AGENT_VIEWER) and must exist and be seeded beforehand.","triggerScenarios":"Passing a typo'd or invented accessRoleId (e.g. 'AGENT_READ'), passing a role _id where an identifier string is expected, or running against a database where the role-seeding migration has not executed. Also triggered after a roles collection reset/wipe without re-seeding.","commonSituations":"Fresh deploy where the access-roles seed script did not run; renaming a role identifier in code without a migration; environments sharing a DB where another tenant wiped roles; tests against a mock db that does not implement findRoleByIdentifier.","solutions":["Use the AccessRoleIds enum/constant for accessRoleId instead of a hand-typed string, so a typo becomes a compile/lint error.","Run the role-seeding migration/script for the environment and verify db.findRoleByIdentifier(AccessRoleIds.AGENT_VIEWER) returns a document.","Log accessRoleId and role.resourceType at the call site to confirm the expected identifier is being sent.","If you extended resource types, ensure the matching role documents for the new resourceType were inserted."],"exampleFix":"// before\nawait grantPermission({ ..., accessRoleId: 'AGENT_READ' });\n\n// after\nconst { AccessRoleIds } = require('./roleConstants');\nawait grantPermission({ ..., accessRoleId: AccessRoleIds.AGENT_VIEWER });","handlingStrategy":"validation","validationCode":"const role = await db.findRoleByIdentifier(accessRoleId);\nif (!role) {\n  throw new Error(`Role ${accessRoleId} not found. Has the role-seeding migration run?`);\n}","typeGuard":"const isKnownAccessRole = (id) => Object.values(AccessRoleIds).includes(id);","tryCatchPattern":"try {\n  await grantPermission({ ..., accessRoleId });\n} catch (err) {\n  if (err.message.startsWith('Role ') && err.message.endsWith(' not found')) {\n    return res.status(400).json({ message: 'Unknown access role.' });\n  }\n  throw err;\n}","preventionTips":["Reference access roles only via the AccessRoleIds enum.","Include a role-seeding step in deploy/migration scripts and assert it succeeded.","Add a startup health check that verifies expected roles exist."],"tags":["permissions","config","roles","seeding"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}