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

  1. Pass overrideExisting: true to overwrite the existing object.
  2. Use a unique blob name per save.
  3. Call ExistsAsync beforehand and branch accordingly.
  4. 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

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


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/a8841adaf0b18544. Report an issue: GitHub.