abpframework/abp · error · BlobAlreadyExistsException

Saving BLOB '{args.BlobName}' does already exists in the con

Error message

Saving BLOB '{args.BlobName}' does already exists in the container '{containerName}'! Set OverrideExisting if it should be overwritten.

What it means

Thrown by AwsBlobProvider.SaveAsync when saving a blob with OverrideExisting=false while an object with the same calculated name already exists in the S3 bucket. It protects against unintended overwrites by calling BlobExistsAsync before any PutObject attempt. The exception is raised inside the using-block of the AmazonS3Client, before the upload path is chosen.

Source

Thrown at framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs:44

        IAmazonS3ClientFactory amazonS3ClientFactory,
        IBlobNormalizeNamingService blobNormalizeNamingService)
    {
        AwsBlobNameCalculator = awsBlobNameCalculator;
        AmazonS3ClientFactory = amazonS3ClientFactory;
        BlobNormalizeNamingService = blobNormalizeNamingService;
    }

    public override async Task SaveAsync(BlobProviderSaveArgs args)
    {
        var blobName = AwsBlobNameCalculator.Calculate(args);
        var configuration = args.Configuration.GetAwsConfiguration();
        var containerName = GetContainerName(args);

        using (var amazonS3Client = await GetAmazonS3Client(args))
        {
            if (!args.OverrideExisting && await BlobExistsAsync(amazonS3Client, containerName, blobName))
            {
                throw new BlobAlreadyExistsException(
                    $"Saving BLOB '{args.BlobName}' does already exists in the container '{containerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
            }

            if (configuration.CreateContainerIfNotExists)
            {
                await CreateContainerIfNotExists(amazonS3Client, containerName);
            }

            if (!RequiresRetrySafeUpload(args))
            {
                await PutObjectAsync(amazonS3Client, containerName, blobName, args.BlobStream, configuration, args.CancellationToken);
                return;
            }

            // The SDK can not retry the upload of a non-seekable stream (like an encrypting
            // stream). A small source with a known length is buffered in memory and uploaded
            // as a retryable PutObject; anything larger (or with an unknown length) goes
            // through a TransferUtility multipart upload, which buffers and retries part by part

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Pass overrideExisting: true when the new content should replace the existing object.
  2. Use a unique key per save (GUID/version suffix) so collisions cannot occur.
  3. Call ExistsAsync beforehand and branch on the result.
  4. Delete the stale object before re-saving if overwrite semantics are not desired but the key must be reused.

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))
{
    // existing key; choose overwrite, rename, or abort
    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: Invoking SaveAsync on a blob container backed by the AWS provider where AwsBlobNameCalculator.Calculate yields a key that already exists in the bucket, with args.OverrideExisting set to its default (false). Triggers on retries of an upload that partially or fully succeeded.

Common situations: Stable deterministic keys (hashes, user IDs) re-saved on profile updates, race conditions between concurrent producers, retry of a de-duplicated upload after the first attempt completed server-side, or migration scripts that re-run.

Related errors


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