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 AliyunBlobProvider.SaveAsync when a blob is saved without OverrideExisting=true and an object with the same (calculated) blob name already exists in the OSS bucket. It is a data-integrity guard preventing accidental silent overwrites of existing stored objects. The check first confirms the bucket exists (DoesBucketExist) and then that the object exists (DoesObjectExist) before PutObject is ever called.

Source

Thrown at framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs:45

        var aliyunConfig = blobContainerConfiguration.GetAliyunConfiguration();
        return OssClientFactory.Create(aliyunConfig);
    }

    protected virtual IOss GetOssClient(AliyunBlobProviderConfiguration aliyunConfig)
    {
        return OssClientFactory.Create(aliyunConfig);
    }


    public override Task SaveAsync(BlobProviderSaveArgs args)
    {
        var containerName = GetContainerName(args);
        var blobName = AliyunBlobNameCalculator.Calculate(args);
        var aliyunConfig = args.Configuration.GetAliyunConfiguration();
        var ossClient = GetOssClient(aliyunConfig);
        if (!args.OverrideExisting && BlobExists(ossClient, 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 (aliyunConfig.CreateContainerIfNotExists)
        {
            if (!ossClient.DoesBucketExist(containerName))
            {
                ossClient.CreateBucket(containerName);
            }
        }
        ossClient.PutObject(containerName, blobName, args.BlobStream);
        return Task.CompletedTask;
    }

    public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
    {
        var containerName = GetContainerName(args);
        var blobName = AliyunBlobNameCalculator.Calculate(args);
        var ossClient = GetOssClient(args.Configuration);
        if (!BlobExists(ossClient, containerName, blobName))

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. If overwriting is intended, pass overrideExisting: true to the SaveAsync call so the existence check is skipped.
  2. If the object is stale, delete it first (DeleteAsync) or confirm it should not be recreated.
  3. Generate a unique blob name (e.g. append a GUID or timestamp) when each upload must create a distinct object.
  4. Before saving, call ExistsAsync to branch your logic instead of relying on the throw.

Example fix

// before
await container.SaveAsync("profile.png", stream);

// after (overwrite is desired)
await container.SaveAsync("profile.png", stream, overrideExisting: true);

// after (unique per upload)
await container.SaveAsync($"profile-{Guid.NewGuid():N}.png", stream);
Defensive patterns

Strategy: validation

Validate before calling

// Check existence before saving when overwrite is not desired
if (await container.ExistsAsync(blobName))
{
    // decide: skip, rename, or explicitly overwrite
    return;
}
await container.SaveAsync(blobName, stream);

Type guard

if (!args.OverrideExisting && await container.ExistsAsync(blobName)) { /* will throw on save */ }

Try / catch

try
{
    await container.SaveAsync(blobName, stream);
}
catch (BlobAlreadyExistsException ex)
{
    // handle: rename key, prompt user, or retry with overrideExisting: true
}

Prevention

When it happens

Trigger: Calling IBlobContainer.SaveAsync (or the underlying BlobProvider SaveAsync) for a blobName whose AliyunBlobNameCalculator.Calculate result already maps to an existing OSS object, while args.OverrideExisting is false (the default). Also triggered by re-saving after a previous successful PutObject under the same name.

Common situations: Re-uploading an avatar or document whose key is stable (e.g. user-id based), replaying an upload after a transient error that actually completed server-side, or multiple concurrent writers racing to create the same key. Also when a previous run left the object in place and the retry did not set OverrideExisting.

Related errors


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