{"record":{"id":"cc807efaf982081e","repo":"danny-avila/LibreChat","slug":"requiredpermission-must-be-a-positive-number","errorCode":null,"errorMessage":"requiredPermission must be a positive number","messagePattern":"requiredPermission must be a positive number","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/api/src/acl/accessControlService.ts","lineNumber":361,"sourceCode":"   * @param {number} params.requiredPermissions - The permission bits required (e.g., 1 for VIEW, 3 for VIEW+EDIT)\n   * @returns {Promise<boolean>} Whether the user has the required permission bits\n   */\n  public async checkPermission({\n    userId,\n    role,\n    resourceType,\n    resourceId,\n    requiredPermission,\n  }: {\n    userId: string;\n    role?: string | null;\n    resourceType: ResourceType;\n    resourceId: string | Types.ObjectId;\n    requiredPermission: number;\n  }): Promise<boolean> {\n    try {\n      if (typeof requiredPermission !== 'number' || requiredPermission < 1) {\n        throw new Error('requiredPermission must be a positive number');\n      }\n\n      this.validateResourceType(resourceType);\n\n      // Get all principals for the user (user + groups + public)\n      const principals = await this._dbMethods.getUserPrincipals({ userId, role });\n\n      if (principals.length === 0) {\n        return false;\n      }\n\n      return await this._dbMethods.hasPermission(\n        principals,\n        resourceType,\n        resourceId,\n        requiredPermission,\n      );\n    } catch (error) {","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/acl/accessControlService.ts#L343-L379","documentation":"checkPermission (singular requiredPermission) guards the permission check the same way the plural variants do: the requested bit mask must be a positive number. The error message uses the singular form to distinguish it from the list-style methods. Note the catch block only re-throws this specific validation error; other errors return false.","triggerScenarios":"Calling checkPermission with requiredPermission = 0, undefined, NaN, a string, or a negative number; computing the bit from user input that produced no bits.","commonSituations":"A gating call that defaults requiredPermission to 0 when nothing is selected; passing the permission name instead of the bit; arithmetic that masks the value to 0.","solutions":["Pass a PermissionBits value (e.g. PermissionBits.VIEW).","Default to PermissionBits.VIEW when the caller has no explicit requirement.","Remember other failures inside checkPermission return false (not throw) — only this validation surfaces."],"exampleFix":"// before\nconst ok = await checkPermission({ userId, resourceType, resourceId, requiredPermission: 0 });\n\n// after\nimport { PermissionBits } from 'librechat-data-provider';\nconst ok = await checkPermission({\n  userId,\n  resourceType,\n  resourceId,\n  requiredPermission: PermissionBits.VIEW,\n});","handlingStrategy":"validation","validationCode":"import { PermissionBits } from 'librechat-data-provider';\nfunction assertPermissionMask(v: unknown): number {\n  if (typeof v !== 'number' || !Number.isFinite(v) || v < 1) {\n    throw new Error('requiredPermission must be a positive number');\n  }\n  return v;\n}","typeGuard":"const isPermissionMask = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v) && v >= 1;","tryCatchPattern":null,"preventionTips":["Pass PermissionBits.VIEW (or a higher mask) explicitly.","Remember checkPermission returns false (does not throw) for non-validation failures.","Default to PermissionBits.VIEW rather than 0."],"tags":["acl","validation","permissions","permission-bits"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}