{"record":{"id":"f746026fbda586bf","repo":"immich-app/immich","slug":"quota-has-been-exceeded","errorCode":null,"errorMessage":"Quota has been exceeded!","messagePattern":"Quota has been exceeded!","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/asset-media.service.ts","lineNumber":370,"sourceCode":"    }\n\n    const album = await this.albumRepository.getById(sharedLink.albumId, { withAssets: false });\n    if (!album) {\n      return;\n    }\n\n    await this.albumRepository.addAssetIds(album.id, [assetId]);\n    const userIds = album.albumUsers.map(({ user }) => user.id);\n    await this.eventRepository.emit('AlbumUpdate', {\n      id: album.id,\n      userIds,\n      recipientIds: userIds,\n    });\n  }\n\n  private requireQuota(auth: AuthDto, size: number) {\n    if (auth.user.quotaSizeInBytes !== null && auth.user.quotaSizeInBytes < auth.user.quotaUsageInBytes + size) {\n      throw new BadRequestException('Quota has been exceeded!');\n    }\n  }\n}\n","sourceCodeStart":352,"sourceCodeEnd":374,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/asset-media.service.ts#L352-L374","documentation":"requireQuota enforces the per-user storage quota: if the user has quotaSizeInBytes set and the incoming file would push quotaUsageInBytes beyond it, uploadAsset throws BadRequestException('Quota has been exceeded!'). It is a deliberate capacity limit, not a bug.","triggerScenarios":"POST /api/assets where quotaSizeInBytes !== null and quotaSizeInBytes < quotaUsageInBytes + file.size for the authenticated user.","commonSituations":"Free-tier or restricted accounts uploading large videos; backup tools bulk-syncing an entire library against a small quota; shared-link uploads consuming another user's quota.","solutions":["Free space by deleting unneeded assets (empty trash) and retry.","Ask an admin to raise the user's quota (Admin UI → Users → Quota).","Set the user's quota to null (unlimited) if appropriate.","Check the user's usage beforehand (GET /api/users/me) and skip uploads that would exceed the remaining space."],"exampleFix":"// before\nawait upload(file); // fails at quota limit\n// after\nconst me = await getUserInfo();\nconst remaining = (me.quotaSizeInBytes ?? Infinity) - me.quotaUsageInBytes;\nif (file.size > remaining) throw new Error(`Skipping ${file.name}: only ${remaining} bytes of quota left`);\nawait upload(file);","handlingStrategy":"validation","validationCode":"const me = await getUserInfo();\nconst remaining = (me.quotaSizeInBytes ?? Infinity) - me.quotaUsageInBytes;\nif (file.size > remaining) throw new Error(`Quota exceeded: need ${file.size}, have ${remaining}`);","typeGuard":null,"tryCatchPattern":"try { await upload(file); } catch (e) { if (String(e).includes('Quota has been exceeded')) notifyUserToFreeSpaceOrUpgrade(); else throw e; }","preventionTips":["Check remaining quota before each upload, especially batch uploads","Sort uploads small-first so partial batches still fit","Periodically empty trash to reclaim quota","Set quota to unlimited for backup-automation accounts"],"tags":["quota","upload","bad-request","limit-exceeded"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}