danny-avila/LibreChat · error · Error
Group principal not found
Error message
Group principal not found
What it means
ensureLocalGroupPrincipalExists() in PermissionService.js:46 throws when db.findGroupById(principalId) returns null — the principalId supplied for a GROUP principal does not resolve to an existing local group. Mirrors the user principal check; prevents phantom-group ACL entries.
Source
Thrown at api/server/services/PermissionService.js:46
const validateResourceType = (resourceType) => {
const validTypes = Object.values(ResourceType);
if (!validTypes.includes(resourceType)) {
throw new Error(`Invalid resourceType: ${resourceType}. Valid types: ${validTypes.join(', ')}`);
}
};
const ensureLocalUserPrincipalExists = async (principalId) => {
const user = await db.findUser({ _id: principalId }, '_id');
if (!user) {
throw new Error('User principal not found');
}
return user._id.toString();
};
const ensureLocalGroupPrincipalExists = async (principalId) => {
const group = await db.findGroupById(principalId, { _id: 1 });
if (!group) {
throw new Error('Group principal not found');
}
return group._id.toString();
};
/**
* @import { TPrincipal } from 'librechat-data-provider'
*/
/**
* Grant a permission to a principal for a resource using a role
* @param {Object} params - Parameters for granting role-based permission
* @param {string} params.principalType - PrincipalType.USER, PrincipalType.GROUP, or PrincipalType.PUBLIC
* @param {string|mongoose.Types.ObjectId|null} params.principalId - The ID of the principal (null for PrincipalType.PUBLIC)
* @param {string} params.resourceType - Type of resource (e.g., 'agent')
* @param {string|mongoose.Types.ObjectId} params.resourceId - The ID of the resource
* @param {string} params.accessRoleId - The ID of the role (e.g., AccessRoleIds.AGENT_VIEWER, AccessRoleIds.AGENT_EDITOR)
* @param {string|mongoose.Types.ObjectId} params.grantedBy - User ID granting the permission
* @param {mongoose.ClientSession} [params.session] - Optional MongoDB session for transactions
* @returns {Promise<Object>} The created or updated ACL entryView on GitHub (pinned to 5ff282f900)
Solutions
- Confirm the group still exists (db.findGroupById) before issuing the grant.
- If using Entra groups, ensure the Entra-to-local group sync has materialized the group.
- Refresh the group list in the UI and reselect if the group was removed.
Defensive patterns
Strategy: validation
Validate before calling
async function assertGroupExists(principalId) {
const g = await db.findGroupById(principalId, { _id: 1 });
if (!g) throw new Error(`no group for ${principalId}`);
} Prevention
- When using Entra groups, ensure local sync has materialized them before granting.
- Refresh group lists in the UI before allowing a share action.
When it happens
Trigger: grantPermission is called with principalType=GROUP and a principalId that is a valid ObjectId but no group with that _id exists. Occurs when sharing with a group that was deleted, or when an Entra-synced group id is used but local group sync has not run.
Common situations: Group was deleted between the UI listing it and the grant call. Entra ID groups feature enabled but the group has not yet been mirrored locally. Stale group id cached on the client.
Related errors
- Invalid resourceType: ${resourceType}. Valid types: ${validT
- User principal not found
- Invalid principal type: ${principalType}
- Principal ID is required for user, group, and role principal
- Invalid role ID: ${principalId}
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/4ba1aab659c449bc.
Report an issue: GitHub.