{"record":{"id":"21ca503cc12278d1","repo":"bitwarden/server","slug":"you-can-only-delete-up-to-500-items-at-a-time-con","errorCode":null,"errorMessage":"You can only delete up to 500 items at a time. Consider using the \"Purge Vault\" option instead.","messagePattern":"You can only delete up to 500 items at a time\\. Consider using the \"Purge Vault\" option instead\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"src/Api/Vault/Controllers/CiphersController.cs","lineNumber":972,"sourceCode":"            throw new NotFoundException();\n        }\n\n        await _cipherService.DeleteAsync(new CipherDetails(cipher), userId, true);\n    }\n\n    [HttpPost(\"{id}/delete-admin\")]\n    [Obsolete(\"This endpoint is deprecated. Use DELETE method instead.\")]\n    public async Task PostDeleteAdmin(Guid id)\n    {\n        await DeleteAdmin(id);\n    }\n\n    [HttpDelete(\"\")]\n    public async Task DeleteMany([FromBody] CipherBulkDeleteRequestModel model)\n    {\n        if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)\n        {\n            throw new BadRequestException(\"You can only delete up to 500 items at a time. \" +\n                \"Consider using the \\\"Purge Vault\\\" option instead.\");\n        }\n\n        var userId = _userService.GetProperUserId(User).Value;\n        await _cipherService.DeleteManyAsync(model.Ids.Select(i => new Guid(i)), userId);\n    }\n\n    [HttpPost(\"delete\")]\n    [Obsolete(\"This endpoint is deprecated. Use DELETE method instead.\")]\n    public async Task PostDeleteMany([FromBody] CipherBulkDeleteRequestModel model)\n    {\n        await DeleteMany(model);\n    }\n\n    [HttpDelete(\"admin\")]\n    public async Task DeleteManyAdmin([FromBody] CipherBulkDeleteRequestModel model)\n    {\n        if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)","sourceCodeStart":954,"sourceCodeEnd":990,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Vault/Controllers/CiphersController.cs#L954-L990","documentation":"DELETE /ciphers (DeleteMany, bulk permanent delete) rejects more than 500 ids on non-self-hosted (cloud) deployments. Self-hosted instances skip the check. Exceeding it returns HTTP 400 and suggests using 'Purge Vault' instead.","triggerScenarios":"A bulk DELETE /ciphers whose `Ids` contains more than 500 entries on a cloud deployment.","commonSituations":"A 'select all + delete' UI over a large vault; a teardown script deleting many items at once; not chunking bulk deletes.","solutions":["Chunk the id list into batches of <= 500 and issue multiple DELETE calls.","For emptying the whole vault, use the Purge Vault option instead of bulk delete.","Surface the 500-item limit in the UI before triggering bulk delete."],"exampleFix":"// before\nDELETE /ciphers  body: { \"ids\": [/* 800 ids */] }\n// after\nDELETE /ciphers  body: { \"ids\": first500 }\nDELETE /ciphers  body: { \"ids\": remaining300 }","handlingStrategy":"validation","validationCode":"const DELETE_LIMIT = 500;\nasync function bulkDelete(ids) {\n  for (const chunk of chunkBy(ids, DELETE_LIMIT)) {\n    await api.delete('/ciphers', { data: { ids: chunk } });\n  }\n}","typeGuard":"function isWithinBulkLimit(ids: unknown[], limit = 500): boolean {\n  return Array.isArray(ids) && ids.length <= limit;\n}","tryCatchPattern":null,"preventionTips":["Chunk bulk deletes to <= 500 ids on cloud.","Use Purge Vault to empty an entire vault rather than bulk delete.","Surface the limit in the UI before mass delete."],"tags":["cipher","delete","bulk","limit","cloud","bad-request"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}