abpframework/abp · error · BlobAlreadyExistsException
Blob '{args.BlobName}' already exists in container '{contain
Error message
Blob '{args.BlobName}' already exists in container '{containerName}'. Set OverrideExisting to true to overwrite. What it means
Thrown by BunnyBlobProvider.SaveAsync when OverrideExisting is false and BlobExistsAsync confirms an object already exists at {containerName}/{blobName} in the Bunny storage zone. The check runs after the storage zone is validated and the BunnyCDNStorage client is obtained, but before the stream is copied and uploaded.
Source
Thrown at framework/src/Volo.Abp.BlobStoring.Bunny/Volo/Abp/BlobStoring/Bunny/BunnyBlobProvider.cs:39
{
BunnyBlobNameCalculator = bunnyBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
BunnyClientFactory = bunnyClientFactory;
}
public async override Task SaveAsync(BlobProviderSaveArgs args)
{
var configuration = args.Configuration.GetBunnyConfiguration();
var containerName = GetContainerName(args);
var blobName = BunnyBlobNameCalculator.Calculate(args);
await ValidateContainerExistsAsync(containerName, configuration);
var bunnyStorage = await GetBunnyCDNStorageAsync(args);
if (!args.OverrideExisting && await BlobExistsAsync(bunnyStorage, containerName, blobName))
{
throw new BlobAlreadyExistsException(
$"Blob '{args.BlobName}' already exists in container '{containerName}'. " +
$"Set {nameof(args.OverrideExisting)} to true to overwrite.");
}
using var memoryStream = new MemoryStream();
await args.BlobStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
await bunnyStorage.UploadAsync(memoryStream, $"{containerName}/{blobName}");
}
public async override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
var blobName = BunnyBlobNameCalculator.Calculate(args);
var containerName = GetContainerName(args);
var bunnyStorage = await GetBunnyCDNStorageAsync(args);
if (!await BlobExistsAsync(bunnyStorage, containerName, blobName))View on GitHub (pinned to 7ed43b1931)
Solutions
- Pass overrideExisting: true to overwrite the existing object.
- Use a unique blob name per save.
- Call ExistsAsync beforehand and branch accordingly.
- Delete the existing object first if the key must be reused without overwrite semantics.
Example fix
// before await container.SaveAsync(key, stream); // after await container.SaveAsync(key, stream, overrideExisting: true);
Defensive patterns
Strategy: validation
Validate before calling
if (await container.ExistsAsync(blobName))
{
await container.SaveAsync(blobName, stream, overrideExisting: true);
return;
}
await container.SaveAsync(blobName, stream); Type guard
bool willConflict = !args.OverrideExisting && await container.ExistsAsync(blobName);
Try / catch
try { await container.SaveAsync(blobName, stream); }
catch (BlobAlreadyExistsException)
{ await container.SaveAsync(blobName, stream, overrideExisting: true); } Prevention
- Pass OverrideExisting when updating.
- Use unique keys for append-only uploads.
- Remember Bunny streams are buffered into a MemoryStream before upload.
When it happens
Trigger: Saving a blob via the Bunny provider where the calculated path already exists and OverrideExisting is false. The existence check lists storage objects in the blob's directory and matches on FullPath.
Common situations: Re-saving a stable-key blob, retrying an upload that already completed, concurrent producers racing for the same path.
Related errors
- Saving BLOB '{args.BlobName}' does already exists in the con
- Saving BLOB '{args.BlobName}' does already exists in the con
- Saving BLOB '{args.BlobName}' does already exists in the con
- Saving BLOB '{args.BlobName}' does already exists in the con
- Invalid directory path generated from blob name.
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/a8841adaf0b18544.
Report an issue: GitHub.