bitwarden/server · warning · BadRequestException
You can only delete up to 500 items at a time.
Error message
You can only delete up to 500 items at a time.
What it means
PUT /ciphers/delete (PutDeleteMany, bulk soft-delete) rejects more than 500 ids on non-self-hosted (cloud) deployments and returns HTTP 400. Unlike the hard-delete variants, no Purge suggestion is appended to this message.
Source
Thrown at src/Api/Vault/Controllers/CiphersController.cs:1051
public async Task PutDeleteAdmin(Guid id)
{
var userId = _userService.GetProperUserId(User).Value;
var cipher = await GetByIdAsyncAdmin(id);
if (cipher == null || !cipher.OrganizationId.HasValue ||
!await CanDeleteOrRestoreCipherAsAdminAsync(cipher.OrganizationId.Value, new[] { cipher.Id }))
{
throw new NotFoundException();
}
await _cipherService.SoftDeleteAsync(new CipherDetails(cipher), userId, true);
}
[HttpPut("delete")]
public async Task PutDeleteMany([FromBody] CipherBulkDeleteRequestModel model)
{
if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)
{
throw new BadRequestException("You can only delete up to 500 items at a time.");
}
var userId = _userService.GetProperUserId(User).Value;
await _cipherService.SoftDeleteManyAsync(model.Ids.Select(i => new Guid(i)), userId);
}
[HttpPut("delete-admin")]
public async Task PutDeleteManyAdmin([FromBody] CipherBulkDeleteRequestModel model)
{
if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)
{
throw new BadRequestException("You can only delete up to 500 items at a time.");
}
if (model == null)
{
throw new NotFoundException();
}View on GitHub (pinned to e93b962371)
Solutions
- Chunk the id list into batches of <= 500 and issue multiple PUT /ciphers/delete calls.
- Surface the 500-item limit in the UI before the user triggers bulk soft-delete.
- Note the cap applies only to cloud, not self-hosted.
Example fix
// before
PUT /ciphers/delete body: { "ids": [/* 700 ids */] }
// after
PUT /ciphers/delete body: { "ids": first500 }
PUT /ciphers/delete body: { "ids": remaining200 } Defensive patterns
Strategy: validation
Validate before calling
const SOFT_DELETE_LIMIT = 500;
async function bulkSoftDelete(ids) {
for (const chunk of chunkBy(ids, SOFT_DELETE_LIMIT)) {
await api.put('/ciphers/delete', { ids: chunk });
}
} Type guard
function isWithinBulkLimit(ids: unknown[], limit = 500): boolean {
return Array.isArray(ids) && ids.length <= limit;
} Prevention
- Chunk soft-delete batches to <= 500 ids on cloud.
- Show the limit in the UI before mass soft-delete.
- Note self-hosted deployments bypass the cap.
When it happens
Trigger: A bulk PUT /ciphers/delete whose `Ids` contains more than 500 entries on a cloud deployment.
Common situations: A 'select all + soft-delete' UI over a large vault; a script soft-deleting many items; not chunking the request.
Related errors
- You can only delete up to 500 items at a time. Consider usin
- You can only archive up to 500 items at a time.
- You can only unarchive up to 500 items at a time.
- No ciphers were archived. Ensure the provided IDs are correc
- Cipher was not encrypted for the current user. Please try ag
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/e54195f20ed1dc21.
Report an issue: GitHub.