danny-avila/LibreChat · error · Error
Invalid principal type: ${principalType}
Error message
Invalid principal type: ${principalType} What it means
grantPermission validates that principalType is one of the PrincipalType enum values (USER, GROUP, PUBLIC, ROLE). Any value outside that set is rejected before any database access. This guards the ACL entry creation path against malformed principal classifications.
Source
Thrown at packages/api/src/acl/accessControlService.ts:62
grantedBy?: string | Types.ObjectId;
session?: ClientSession;
roleId?: string | Types.ObjectId;
expiredAt?: Date;
}): Promise<IAclEntry | null> {
const {
principalType,
principalId,
resourceType,
resourceId,
accessRoleId,
grantedBy,
session,
expiredAt,
} = args;
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 &&
(!principalId || !Types.ObjectId.isValid(principalId))
) {
// User and Group IDs must be valid ObjectIdsView on GitHub (pinned to 5ff282f900)
Solutions
- Pass a value imported directly from PrincipalType (e.g. PrincipalType.USER) rather than a string literal.
- After upgrading librechat-data-provider, diff the PrincipalType enum and update all call sites.
- Add a unit test that exercises grantPermission with every PrincipalType member to catch regressions.
Example fix
// before
await grantPermission({ principalType: 'Users', ... });
// after
import { PrincipalType } from 'librechat-data-provider';
await grantPermission({ principalType: PrincipalType.USER, ... }); Defensive patterns
Strategy: validation
Validate before calling
import { PrincipalType } from 'librechat-data-provider';
const validPrincipalTypes = new Set(Object.values(PrincipalType));
function assertPrincipalType(v: unknown): PrincipalType {
if (typeof v !== 'string' || !validPrincipalTypes.has(v as PrincipalType)) {
throw new Error(`Invalid principal type: ${String(v)}`);
}
return v as PrincipalType;
} Type guard
import { PrincipalType } from 'librechat-data-provider';
const isPrincipalType = (v: unknown): v is PrincipalType =>
typeof v === 'string' && Object.values(PrincipalType).includes(v as PrincipalType); Prevention
- Always import PrincipalType and reference its members; never inline string literals.
- After upgrading librechat-data-provider, grep for PrincipalType usages and reconcile.
- Add a type test that exercises grantPermission for every enum member.
When it happens
Trigger: Calling grantPermission with principalType set to a string not in PrincipalType, e.g. a typo like 'Users', a numeric id, undefined, or a stale enum value after a librechat-data-provider version bump that renamed members.
Common situations: A refactor passes the raw user role string instead of the PrincipalType enum; an upgrade to librechat-data-provider adds/removes enum members and a downstream caller still sends the old literal; deserialized JSON where the field is missing or misspelled.
Related errors
- Invalid resourceType: ${resourceType}. Valid types: ${validT
- Invalid resourceType: ${resourceType}. Valid types: ${validT
- User principal not found
- Group principal not found
- Invalid principal type: ${principalType}
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/9bfb6f9b825e501d.
Report an issue: GitHub.