bitwarden/server · warning · BadRequestException

You can only delete up to 500 folders at a time.

Error message

You can only delete up to 500 folders at a time.

What it means

Thrown by FoldersController.DeleteMany (DELETE /folders) when model.Ids contains more than 500 IDs AND the instance is not self-hosted (_globalSettings.SelfHosted is false). The endpoint is gated behind the VFO1Foundation feature flag. Self-hosted instances have no such limit. The 500-item cap protects cloud database performance during bulk folder deletion.

Source

Thrown at src/Api/Vault/Controllers/FoldersController.cs:122

        }

        await _cipherService.DeleteFolderAsync(folder);
    }

    [HttpPost("{id}/delete")]
    [Obsolete("This endpoint is deprecated. Use DELETE method instead.")]
    public async Task PostDelete(string id)
    {
        await Delete(id);
    }

    [HttpDelete("")]
    [RequireFeature(FeatureFlagKeys.VFO1Foundation)]
    public async Task DeleteMany([FromBody] FolderBulkDeleteRequestModel model)
    {
        if (!_globalSettings.SelfHosted && model.Ids.Count() > 500)
        {
            throw new BadRequestException("You can only delete up to 500 folders at a time.");
        }

        var userId = _userService.GetProperUserId(User).Value;
        await _deleteManyFoldersCommand.DeleteManyAsync(model.Ids, userId);
    }

    [HttpDelete("all")]
    public async Task DeleteAll()
    {
        var userId = _userService.GetProperUserId(User).Value;
        var allFolders = await _folderRepository.GetManyByUserIdAsync(userId);

        foreach (var folder in allFolders)
        {
            await _cipherService.DeleteFolderAsync(folder);
        }
    }
}

View on GitHub (pinned to e93b962371)

Solutions

  1. Batch the deletion into chunks of 500 or fewer IDs per request
  2. Use the DELETE /folders/all endpoint if the intent is to delete every folder
  3. On self-hosted, this limit is not enforced, but batching is still recommended for performance
  4. Implement client-side chunking that splits large ID lists before calling the API

Example fix

// before (sends all at once, fails on cloud if > 500)
await api.DeleteManyFoldersAsync(allFolderIds);

// after (chunked into batches of 500)
const batchSize = 500;
for (let i = 0; i < allFolderIds.length; i += batchSize) {
    const batch = allFolderIds.slice(i, i + batchSize);
    await api.DeleteManyFoldersAsync(batch);
}
Defensive patterns

Strategy: validation

Validate before calling

// Chunk folder IDs before calling bulk delete
const int MaxBatchSize = 500;
foreach (var batch in allFolderIds.Chunk(MaxBatchSize))
{
    await api.DeleteManyFoldersAsync(batch.ToList());
}
// Or: use DELETE /folders/all if deleting everything

Prevention

When it happens

Trigger: Sending a bulk delete request with more than 500 folder IDs on the Bitwarden cloud service; client batching logic that doesn't chunk requests; a script or migration attempting to delete all folders in a single call.

Common situations: Bulk cleanup scripts; client-side 'select all and delete' that sends all IDs at once; migration tooling that doesn't respect API limits.

Related errors


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/c9860c92122153eb. Report an issue: GitHub.