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

  1. Use a role whose resourceType matches the resource being granted on (e.g. AGENT_VIEWER for ResourceType.AGENT).
  2. Drive role selection from the resourceType in the UI so only compatible roles are offered.
  3. 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

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


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/7e57cc2c61463e8a. Report an issue: GitHub.