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 '{args.ContainerName}'! Set OverrideExisting if it should be overwritten. What it means
Thrown by FileSystemBlobProvider.SaveAsync when OverrideExisting is false and a file already exists at the calculated file path (ExistsAsync returns true). It is the filesystem analogue of the cloud providers' BlobAlreadyExistsException, guarding against silent overwrites before DirectoryHelper creates the directory and the file is opened with FileMode.CreateNew.
Source
Thrown at framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs:25
namespace Volo.Abp.BlobStoring.FileSystem;
public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency
{
protected IBlobFilePathCalculator FilePathCalculator { get; }
public FileSystemBlobProvider(IBlobFilePathCalculator filePathCalculator)
{
FilePathCalculator = filePathCalculator;
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
{
var filePath = FilePathCalculator.Calculate(args);
if (!args.OverrideExisting && await ExistsAsync(filePath))
{
throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
}
DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(filePath)!);
var fileMode = args.OverrideExisting
? FileMode.Create
: FileMode.CreateNew;
// A failure is only retried while it is replayable: before OpenFileStream returns
// (the source is untouched), or for a seekable overwrite (the source can seek back
// and FileMode.Create truncates the partial content). Otherwise a retry would
// replay a half-consumed source or hit the file a failed CreateNew attempt left behind.
long sourcePosition;
try
{
sourcePosition = args.BlobStream.CanSeek && fileMode == FileMode.Create ? args.BlobStream.Position : -1;
}
catch (Exception ex) when (ex is NotSupportedException || ex is IOException)View on GitHub (pinned to 7ed43b1931)
Solutions
- Pass overrideExisting: true to replace the existing file (the provider then uses FileMode.Create).
- Use a unique blob/file name per save.
- Call ExistsAsync first and branch.
- Delete the existing file before re-saving if overwrite semantics are unwanted.
Example fix
// before
await container.SaveAsync("data.bin", stream);
// after
await container.SaveAsync("data.bin", 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)
{ /* rename or retry with overrideExisting: true */ } Prevention
- Pass OverrideExisting when updating an existing file.
- Use unique names for immutable uploads.
- In multi-instance deployments on a shared filesystem, coordinate write paths to avoid races.
When it happens
Trigger: Saving a blob through the FileSystem provider where the file at FilePathCalculator.Calculate(args) already exists and OverrideExisting is false. The existence check uses File.Exists on the resolved path.
Common situations: Re-saving a file under a stable path, retrying a write that completed, persistent local storage where keys collide, or multiple app instances writing to a shared filesystem 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
- Blob '{args.BlobName}' already exists in container '{contain
- The length of the stream is not available!
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/9b47e92daaa78cf2.
Report an issue: GitHub.