danny-avila/LibreChat · error · Error
Role ${accessRoleId} is for ${role.resourceType} resources,
Error message
Role ${accessRoleId} is for ${role.resourceType} resources, not ${resourceType} What it means
Even after a role is found, grantPermission enforces that role.resourceType equals the requested resourceType. A role defined for 'agent' resources cannot be applied to a 'prompt' resource, preventing permission bits from being misapplied across resource kinds.
Source
Thrown at packages/api/src/acl/accessControlService.ts:98
// User and Group IDs must be valid ObjectIds
throw new Error(`Invalid principal ID: ${principalId}`);
}
if (!resourceId || !Types.ObjectId.isValid(resourceId)) {
throw new Error(`Invalid resource ID: ${resourceId}`);
}
this.validateResourceType(resourceType as ResourceType);
// Get the role to determine permission bits
const role = await this._dbMethods.findRoleByIdentifier(accessRoleId);
if (!role) {
throw new Error(`Role ${accessRoleId} not found`);
}
// Ensure the role is for the correct resource type
if (role.resourceType !== resourceType) {
throw new Error(
`Role ${accessRoleId} is for ${role.resourceType} resources, not ${resourceType}`,
);
}
return await this._dbMethods.grantPermission(
principalType,
principalId,
resourceType,
resourceId,
role.permBits,
grantedBy,
session,
role._id,
expiredAt,
);
} catch (error) {
logger.error(
`[PermissionService.grantPermission] Error: ${error instanceof Error ? error.message : ''}`,
error,View on GitHub (pinned to 5ff282f900)
Solutions
- Use a role whose resourceType matches the resource being granted on (e.g. AGENT_VIEWER for ResourceType.AGENT).
- Drive role selection from the resourceType in the UI so only compatible roles are offered.
- Add a guard in the caller: assert role definitions exist for every ResourceType you grant on.
Example fix
// before
await grantPermission({
resourceType: ResourceType.PROMPT,
accessRoleId: AccessRoleIds.AGENT_VIEWER, // role.resourceType === 'agent'
...,
});
// after
await grantPermission({
resourceType: ResourceType.PROMPT,
accessRoleId: AccessRoleIds.PROMPT_VIEWER, // role.resourceType === 'prompt'
...,
}); Defensive patterns
Strategy: validation
Validate before calling
// ensure role.resourceType matches the resourceType before granting
if (role.resourceType !== resourceType) {
throw new Error(`Role ${accessRoleId} is for ${role.resourceType}, not ${resourceType}`);
} Prevention
- Drive role selection from the chosen resourceType in the UI so only compatible roles are selectable.
- Pair each ResourceType with its own role identifiers in a lookup table.
- Add an integration test per (resourceType, role) pair.
When it happens
Trigger: Pairing an agent-scoped role (e.g. AGENT_VIEWER) with resourceType: ResourceType.PROMPT, or any cross-kind mismatch between the role document and the grant request.
Common situations: UI lets the user pick a role and a resource independently and they are mismatched; copy-pasting a grant call and changing resourceType but not accessRoleId; adding a new ResourceType without defining roles for it.
Related errors
- Invalid role ID: ${principalId}
- Role ${accessRoleId} is for ${role.resourceType} resources,
- Invalid role ID: ${principalId}
- Role ${accessRoleId} not found
- Invalid resourceType: ${resourceType}. Valid types: ${validT
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/7e57cc2c61463e8a.
Report an issue: GitHub.