danny-avila/LibreChat · error · Error
Principal ID is required for user, group, and role principal
Error message
Principal ID is required for user, group, and role principals
What it means
grantPermission() in PermissionService.js:81 throws this when principalType is anything other than PUBLIC and principalId is missing/null. PUBLIC is the only principal that legitimately has no id (it represents everyone); user, group, and role principals must carry an identifier.
Source
Thrown at api/server/services/PermissionService.js:81
* @param {mongoose.ClientSession} [params.session] - Optional MongoDB session for transactions
* @returns {Promise<Object>} The created or updated ACL entry
*/
const grantPermission = async ({
principalType,
principalId,
resourceType,
resourceId,
accessRoleId,
grantedBy,
session,
}) => {
try {
if (!Object.values(PrincipalType).includes(principalType)) {
throw new Error(`Invalid principal type: ${principalType}`);
}
if (principalType !== PrincipalType.PUBLIC && !principalId) {
throw new Error('Principal ID is required for user, group, and role principals');
}
// Validate principalId based on type
if (principalId && principalType === PrincipalType.ROLE) {
// Role IDs are strings (role names)
if (typeof principalId !== 'string' || principalId.trim().length === 0) {
throw new Error(`Invalid role ID: ${principalId}`);
}
} else if (
principalType &&
principalType !== PrincipalType.PUBLIC &&
!mongoose.Types.ObjectId.isValid(principalId)
) {
// User and Group IDs must be valid ObjectIds
throw new Error(`Invalid principal ID: ${principalId}`);
}
if (!resourceId || !mongoose.Types.ObjectId.isValid(resourceId)) {View on GitHub (pinned to 5ff282f900)
Solutions
- For USER/GROUP, supply a valid ObjectId; for ROLE, supply the role name string.
- If you intended 'everyone', use PrincipalType.PUBLIC with no principalId instead.
- Validate on the client that a principal is selected before enabling the submit action.
Example fix
// before
grantPermission({ principalType: PrincipalType.USER, principalId: null, ... });
// after
grantPermission({ principalType: PrincipalType.USER, principalId: selectedUserId, ... }); Defensive patterns
Strategy: validation
Validate before calling
function assertPrincipalId(principalType, principalId) {
if (principalType !== PrincipalType.PUBLIC && !principalId) {
throw new Error(`principalId required for ${principalType}`);
}
} Type guard
const hasRequiredPrincipalId = (type, id) => type === PrincipalType.PUBLIC ? true : !!id;
Prevention
- Bind the selected principal's id in the same handler that sets principalType.
- Disable the submit action until a non-PUBLIC principal has an id.
When it happens
Trigger: A caller sets principalType to USER/GROUP/ROLE but omits principalId or passes null/undefined. Fires after the principalType enum check passes, so it specifically catches the 'right type, no id' mistake.
Common situations: UI bug where the selected user/group did not get bound to the request body. A refactor that decoupled principalType from principalId population. Confusing ROLE (id is the role name string) with a missing id.
Related errors
- Invalid resourceType: ${resourceType}. Valid types: ${validT
- User principal not found
- Group principal not found
- Invalid principal type: ${principalType}
- Invalid role ID: ${principalId}
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/4a838fa2b9fa5caf.
Report an issue: GitHub.