files-community/Files · error · IOException

Failed to connect to FTP server.

Error message

Failed to connect to FTP server.

What it means

Thrown by FtpStorageFolder.CreateFolderAsync (Files.App/Utils) when EnsureConnectedAsync returns false - the client could not connect. Identical root cause to error 10 but on the folder-creation path; runs inside SafetyExtensions.Wrap with RetryWithCredentialsAsync.

Source

Thrown at src/Files.App/Utils/Storage/StorageItems/FtpStorageFolder.cs:241

						throw new FileAlreadyExistsException(desiredName);

					return null;
				}

				throw new IOException($"Failed to create file {remotePath}.");
			}, ((IPasswordProtectedItem)this).RetryWithCredentialsAsync));
		}

		public override IAsyncOperation<BaseStorageFolder> CreateFolderAsync(string desiredName)
			=> CreateFolderAsync(desiredName, CreationCollisionOption.FailIfExists);
		public override IAsyncOperation<BaseStorageFolder> CreateFolderAsync(string desiredName, CreationCollisionOption options)
		{
			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.");
				}

				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}"));

View on GitHub (pinned to 68c68a58d4)

Solutions

  1. Trigger the credentials retry path (RetryWithCredentialsAsync) to re-prompt the user.
  2. Verify host/port/encryption configuration matches the server.
  3. Check network and firewall reachability to the FTP control and passive data ports.
  4. Catch IOException and classify it as a connection failure for user messaging.
  5. Recreate the folder handle from a fresh connection if the client is stale.
Defensive patterns

Strategy: retry

Validate before calling

// Confirm connectivity before creating the folder.
using var c = GetFtpClient();
if (!await c.EnsureConnectedAsync())
    throw new IOException("Cannot reach FTP server; check credentials and network.");

Try / catch

try { await folder.CreateFolderAsync(name, options); }
catch (IOException ex) when (ex.Message.Contains("connect to FTP"))
{ /* re-prompt credentials, then retry */ }

Prevention

When it happens

Trigger: CreateFolderAsync where EnsureConnectedAsync fails before the DirectoryExists/CreateDirectory calls. Wrong credentials, unreachable host, blocked port, or failed TLS handshake.

Common situations: Expired stored password; server downtime; firewall blocking control/data ports; cert trust change; stale client in a pool.

Related errors


AI-assisted analysis of files-community/Files@68c68a58d4 (2026-08-13). Data as JSON: /api/errors/fe1e5088bbf1dace. Report an issue: GitHub.