files-community/Files · error · IOException
Couldn't generate unique name. File skipped.
Error message
Couldn't generate unique name. File skipped.
What it means
Thrown by FtpStorageFolder.CreateFileAsync when UploadStream returns FtpStatus.Skipped. With overwrite=false the upload uses FtpRemoteExists.Skip, so any pre-existing file at the target path causes the server to skip the upload and FluentFTP reports Skipped. The comment indicates this path was meant to honor a GenerateUniqueName collision option that this overload does not actually implement.
Source
Thrown at src/Files.App.Storage/Ftp/FtpStorageFolder.cs:147
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
var newPath = $"{Id}/{desiredName}";
if (overwrite && await ftpClient.FileExists(newPath, cancellationToken))
throw new IOException("File already exists.");
using var stream = new MemoryStream();
var result = await ftpClient.UploadStream(stream, newPath, overwrite ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip, token: cancellationToken);
if (result == FtpStatus.Success)
{
// Success
return new FtpStorageFile(newPath, desiredName, this);
}
else if (result == FtpStatus.Skipped)
{
// Throw exception since flag CreationCollisionOption.GenerateUniqueName was not satisfied
throw new IOException("Couldn't generate unique name. File skipped.");
}
else
{
// File creation failed
throw new IOException("File creation failed.");
}
}
/// <inheritdoc/>
public async Task<IChildFolder> CreateFolderAsync(string desiredName, bool overwrite = default, CancellationToken cancellationToken = default)
{
using var ftpClient = GetFtpClient();
await ftpClient.EnsureConnectedAsync(cancellationToken);
var newPath = $"{Id}/{desiredName}";
if (overwrite && await ftpClient.DirectoryExists(newPath, cancellationToken))
throw new IOException("Directory already exists.");
View on GitHub (pinned to 68c68a58d4)
Solutions
- Pass overwrite=true if replacing the existing file is acceptable.
- Generate a unique name at the call site before invoking CreateFileAsync (the overload here does not implement GenerateUniqueName despite the comment).
- Pre-check with ftpClient.FileExists and either rename or delete the conflicting file first.
- Fix the inverted overwrite guard (see error 1) so the existence conflict is reported at a deterministic point.
Example fix
// before
var file = await folder.CreateFileAsync(name, overwrite: false, ct);
// after
var attempt = 0;
string unique = name;
while (await FtpExists(folder, unique))
unique = $"{Path.GetFileNameWithoutExtension(name)} ({++attempt}){Path.GetExtension(name)}";
var file = await folder.CreateFileAsync(unique, overwrite: false, ct); Defensive patterns
Strategy: validation
Validate before calling
// Ensure a unique name before creating when overwrite is false.
string name = desiredName;
int i = 1;
while (!overwrite && await FtpFileExists(folder, name))
name = $"{Path.GetFileNameWithoutExtension(desiredName)} ({i++}){Path.GetExtension(desiredName)}";
await folder.CreateFileAsync(name, overwrite, ct); Try / catch
try { return await folder.CreateFileAsync(name, false, ct); }
catch (IOException ex) when (ex.Message.Contains("skipped", StringComparison.OrdinalIgnoreCase))
{ /* generate a unique name and retry */ } Prevention
- This overload does not implement GenerateUniqueName despite the comment; compute unique names yourself.
- Pre-check existence to avoid relying on the Skipped result.
- Pass overwrite=true when replacement is acceptable.
When it happens
Trigger: CreateFileAsync with overwrite=false (default) when {Id}/{desiredName} already exists on the FTP server; the inverted overwrite guard at line 133 does not catch it, so the skip surfaces here.
Common situations: Pasting a file into a folder that already contains a file of the same name with the default 'fail if exists' collision option; uploads after a partial/interrupted prior upload left a zero-byte stub.
Related errors
- File already exists.
- File creation failed.
- Failed to move file from {Path} to {destFolder}.
- Failed to create file {remotePath}.
- Failed to move folder from {Path} to {destFolder}.
AI-assisted analysis of files-community/Files@68c68a58d4 (2026-08-13).
Data as JSON: /api/errors/6190f9a494822f8c.
Report an issue: GitHub.