bitwarden/server · warning · BadRequestException
You can only archive up to 500 items at a time.
Error message
You can only archive up to 500 items at a time.
What it means
PUT /ciphers/archive (PutArchiveMany, bulk) rejects requests with more than 500 ids when the deployment is NOT self-hosted (cloud only). The cap protects cloud throughput; self-hosted instances bypass it. Exceeding it returns HTTP 400.
Source
Thrown at src/Api/Vault/Controllers/CiphersController.cs:904
var userId = _userService.GetProperUserId(User).Value;
var archivedCipherOrganizationDetails = await _archiveCiphersCommand.ArchiveManyAsync([id], userId);
if (archivedCipherOrganizationDetails.Count == 0)
{
throw new BadRequestException("Cipher was not archived. Ensure the provided ID is correct and you have permission to archive it.");
}
var archivedCipher = archivedCipherOrganizationDetails.First();
return new CipherResponseModel(archivedCipher, await _userService.GetUserByPrincipalAsync(User), await GetOrganizationAbilityAsync(archivedCipher), _globalSettings);
}
[HttpPut("archive")]
public async Task<ListResponseModel<CipherResponseModel>> PutArchiveMany([FromBody] CipherBulkArchiveRequestModel model)
{
if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)
{
throw new BadRequestException("You can only archive up to 500 items at a time.");
}
var userId = _userService.GetProperUserId(User).Value;
var user = await _userService.GetUserByPrincipalAsync(User);
var cipherIdsToArchive = new HashSet<Guid>(model.Ids);
var archivedCiphers = await _archiveCiphersCommand.ArchiveManyAsync(cipherIdsToArchive, userId);
if (archivedCiphers.Count == 0)
{
throw new BadRequestException("No ciphers were archived. Ensure the provided IDs are correct and you have permission to archive them.");
}
var organizationAbilities = await GetOrganizationAbilitiesAsync(archivedCiphers);
var responses = archivedCiphers.Select(cipher =>
new CipherResponseModel(cipher, user, GetOrganizationAbility(cipher, organizationAbilities), _globalSettings)).ToArray();
View on GitHub (pinned to e93b962371)
Solutions
- Chunk the id list into batches of <= 500 and issue multiple requests.
- Surface the 500-item limit in the UI before the user triggers a bulk archive.
- If operating self-hosted, note the cap does not apply there.
Example fix
// before
PUT /ciphers/archive body: { "ids": [/* 750 ids */] }
// after
PUT /ciphers/archive body: { "ids": first500 }
PUT /ciphers/archive body: { "ids": remaining250 } Defensive patterns
Strategy: validation
Validate before calling
const ARCHIVE_LIMIT = 500;
async function bulkArchive(ids) {
for (const chunk of chunkBy(ids, ARCHIVE_LIMIT)) {
await api.put('/ciphers/archive', { ids: chunk });
}
}
function chunkBy(arr, n) { const out = []; for (let i = 0; i < arr.length; i += n) out.push(arr.slice(i, i + n)); return out; } Type guard
function isWithinBulkLimit(ids: unknown[], limit = 500): boolean {
return Array.isArray(ids) && ids.length <= limit;
} Prevention
- Always chunk bulk operations into <= 500-id batches on cloud.
- Show the limit in the UI before a 'select all' bulk action.
- Remember self-hosted deployments are exempt from the cap.
When it happens
Trigger: A bulk PUT /ciphers/archive whose `Ids` collection contains more than 500 entries on a cloud (non-self-hosted) deployment.
Common situations: A 'select all + archive' UI action over a large vault; a migration script archiving many items in one call; a client not chunking bulk operations.
Related errors
- You can only delete up to 500 items at a time. Consider usin
- You can only delete 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 archived. Ensure the provided ID is correct a
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/386cdd1258ee81db.
Report an issue: GitHub.