{"record":{"id":"5d9ece26c6055f27","repo":"immich-app/immich","slug":"missing-required-permission-requestedpermission","errorCode":null,"errorMessage":"Missing required permission: ${requestedPermission}","messagePattern":"Missing required permission: (.+?)","errorType":"exception","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"server/src/services/auth.service.ts","lineNumber":235,"sourceCode":"    const { adminRoute, sharedLinkRoute, uri } = metadata;\n    const requestedPermission = metadata.permission ?? Permission.All;\n\n    if (!authDto.user.isAdmin && adminRoute) {\n      this.logger.warn(`Denied access to admin only route: ${uri}`);\n      throw new ForbiddenException('Forbidden');\n    }\n\n    if (authDto.sharedLink && !sharedLinkRoute) {\n      this.logger.warn(`Denied access to non-shared route: ${uri}`);\n      throw new ForbiddenException('Forbidden');\n    }\n\n    if (\n      authDto.apiKey &&\n      requestedPermission !== false &&\n      !isGranted({ requested: [requestedPermission], current: authDto.apiKey.permissions })\n    ) {\n      throw new ForbiddenException(`Missing required permission: ${requestedPermission}`);\n    }\n\n    return authDto;\n  }\n\n  private async validate({ headers, queryParams }: Omit<ValidateRequest, 'metadata'>): Promise<AuthDto> {\n    const shareKey = (headers[ImmichHeader.SharedLinkKey] || queryParams[ImmichQuery.SharedLinkKey]) as string;\n    const shareSlug = (headers[ImmichHeader.SharedLinkSlug] || queryParams[ImmichQuery.SharedLinkSlug]) as string;\n    const session = (headers[ImmichHeader.UserToken] ||\n      headers[ImmichHeader.SessionToken] ||\n      queryParams[ImmichQuery.SessionKey] ||\n      this.getBearerToken(headers) ||\n      this.getCookieToken(headers)) as string;\n    const apiKey = (headers[ImmichHeader.ApiKey] || queryParams[ImmichQuery.ApiKey]) as string;\n\n    if (shareKey) {\n      return this.validateSharedLinkKey(shareKey);\n    }","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/immich-app/immich/blob/f48d4b332127ad365ba256108799ca8f571d2dd5/server/src/services/auth.service.ts#L217-L253","documentation":"Thrown by authenticate() when an API-key-authenticated request does not carry the permission required for the requested operation. isGranted() compares the requested permission against the key's stored permission set and fails the request with 403.","triggerScenarios":"A request authenticates with an API key (authDto.apiKey set), requestedPermission is not false, and the key's permissions lack the requested permission.","commonSituations":"Using an Immich API key created without the needed scope (e.g. asset-scoped key used for library or admin operations); keys from older versions missing new permission slugs; sharing one key across many integrations.","solutions":["Regenerate or edit the API key in Immich user settings, granting the required permission","Recreate the key and update the client's x-api-key header","Verify you are calling the intended endpoint/version for your key's scope"],"exampleFix":"// before\ncurl -H 'x-api-key: OLD_KEY' /api/library\n// after\n// regenerate key with required permission in Immich settings\ncurl -H 'x-api-key: NEW_KEY' /api/library","handlingStrategy":"try-catch","validationCode":"if (!keyPermissions.includes(requiredPermission)) throw new Error('API key lacks ' + requiredPermission);","typeGuard":null,"tryCatchPattern":"try { await api.request(...) } catch (e) { if (e.status === 403 && /Missing required permission/.test(e.message)) { /* prompt to grant key permission */ } throw e; }","preventionTips":["Grant keys only needed permissions but verify against endpoint docs","Re-check key scopes after Immich upgrades","Test each key against the endpoints it will use"],"tags":["auth","api-key","permissions","forbidden"],"backgroundTag":"permission-denied","analyzedSha":"f48d4b332127ad365ba256108799ca8f571d2dd5","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}