files-community/Files · error · IOException
Failed to create folder {desiredName}.
Error message
Failed to create folder {desiredName}. What it means
Thrown by FtpStorageFolder.CreateFolderAsync (Files.App/Utils) when AsyncFtpClient.CreateDirectory returns false. The directory could not be created at {FtpPath}/{desiredName}: usually a missing parent directory (FTP MKD is non-recursive), lack of create permission, invalid name, or the server rejecting the operation.
Source
Thrown at src/Files.App/Utils/Storage/StorageItems/FtpStorageFolder.cs:256
using var ftpClient = GetFtpClient();
if (!await ftpClient.EnsureConnectedAsync())
{
throw new IOException($"Failed to connect to FTP server.");
}
string fileName = $"{FtpPath}/{desiredName}";
if (await ftpClient.DirectoryExists(fileName))
{
var item = new FtpStorageFolder(new StorageFileWithPath(null, fileName));
((IPasswordProtectedItem)item).CopyFrom(this);
return item;
}
bool replaceExisting = options is CreationCollisionOption.ReplaceExisting;
bool isSuccessful = await ftpClient.CreateDirectory(fileName, replaceExisting, cancellationToken);
if (!isSuccessful)
{
throw new IOException($"Failed to create folder {desiredName}.");
}
var folder = new FtpStorageFolder(new StorageFileWithPath(null, $"{Path}/{desiredName}"));
((IPasswordProtectedItem)folder).CopyFrom(this);
return folder;
}, ((IPasswordProtectedItem)this).RetryWithCredentialsAsync));
}
public override IAsyncOperation<BaseStorageFolder> MoveAsync(IStorageFolder destinationFolder)
=> MoveAsync(destinationFolder, NameCollisionOption.FailIfExists);
public override IAsyncOperation<BaseStorageFolder> MoveAsync(IStorageFolder destinationFolder, NameCollisionOption option)
{
return AsyncInfo.Run((cancellationToken) => SafetyExtensions.Wrap<BaseStorageFolder>(async () =>
{
using var ftpClient = GetFtpClient();
if (!await ftpClient.EnsureConnectedAsync())
throw new IOException($"Failed to connect to FTP server.");
View on GitHub (pinned to 68c68a58d4)
Solutions
- Create parent directories first, or use a recursive create that forces intermediate directory creation.
- Sanitize the desired name for the target server's filesystem.
- Check ftpClient.LastReply for the MKD failure code and report it.
- Confirm the FTP account has directory-creation rights on the target.
- Catch IOException and retry once after ensuring the parent exists.
Example fix
// before
bool isSuccessful = await ftpClient.CreateDirectory(fileName, replaceExisting, cancellationToken);
// after
bool isSuccessful = await ftpClient.CreateDirectory(fileName, replaceExisting || forceParents: true, cancellationToken);
if (!isSuccessful)
throw new IOException($"Failed to create folder {desiredName}: {ftpClient.LastReply?.Code} {ftpClient.LastReply?.Message}"); Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the parent directory exists before creating a nested folder.
if (!await ftpClient.DirectoryExists(FtpPath, ct))
await ftpClient.CreateDirectory(FtpPath, true, ct); Try / catch
try { return await folder.CreateFolderAsync(name, options); }
catch (IOException ex) when (ex.Message.Contains("Failed to create folder"))
{ var reply = ftpClient.LastReply; /* inspect and report MKD failure */ throw; } Prevention
- Create parent directories first; FTP MKD is non-recursive.
- Sanitize the name for the target server's filesystem.
- Inspect LastReply for the failure code and report it.
When it happens
Trigger: CreateDirectory(fileName, replaceExisting, ct) returning false after a successful connection and after the DirectoryExists early-return did not apply. Missing parent is the most common cause when creating nested paths in one step.
Common situations: Creating nested folders without creating parents first; accounts restricted below the target; names with illegal characters; servers that disallow overwriting an existing directory.
Related errors
- Directory was not successfully created.
- Failed to connect to FTP server.
- File creation failed.
- Directory already exists.
- Failed to connect to FTP server.
AI-assisted analysis of files-community/Files@68c68a58d4 (2026-08-13).
Data as JSON: /api/errors/da33f12835f89ce8.
Report an issue: GitHub.