danny-avila/LibreChat · error · Error

User principal not found

Error message

User principal not found

What it means

ensureLocalUserPrincipalExists() in PermissionService.js:38 throws when db.findUser({_id: principalId}) returns null — i.e. the principalId passed for a USER principal does not resolve to an existing local user. This is the existence check that prevents ACL entries from referencing phantom users.

Source

Thrown at api/server/services/PermissionService.js:38

/** @type {boolean|null} */
let transactionSupportCache = null;

/**
 * Validates that the resourceType is one of the supported enum values
 * @param {string} resourceType - The resource type to validate
 * @throws {Error} If resourceType is not valid
 */
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

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Verify the principalId corresponds to a currently existing user in the target environment.
  2. If the user was deleted, cancel the share/grant operation rather than retrying.
  3. In multi-tenant setups, confirm the principalId belongs to the same tenant before granting.
Defensive patterns

Strategy: validation

Validate before calling

async function assertUserExists(principalId) {
  const u = await db.findUser({ _id: principalId }, '_id');
  if (!u) throw new Error(`no user for ${principalId}`);
}

Prevention

When it happens

Trigger: grantPermission (or a sibling ACL call) is invoked with principalType=USER and a principalId that is a valid ObjectId shape but does not exist in the users collection. Common right after a user was deleted, or when an id is transcribed from another tenant/environment.

Common situations: Cross-environment copy of an agent share that references a user id not present locally. A user was soft/hard-deleted but still referenced in a pending share operation. Multi-tenant leak where a principalId from tenant A is used in tenant B.

Related errors


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