thephpleague/flysystem · error · UnableToEnableUtf8Mode
Could not set UTF-8 mode for connection: {host}::{port}
Error message
Could not set UTF-8 mode for connection: {host}::{port} What it means
When FtpConnectionOptions has utf8 = true, FtpConnectionProvider::enableUtf8Mode() sends 'OPTS UTF8 ON' via ftp_raw and requires the response code to start with 200 or 202. Any other reply throws UnableToEnableUtf8Mode with 'Could not set UTF-8 mode for connection: host::port'. It fires right after login, during connection setup.
Source
Thrown at src/Ftp/FtpConnectionProvider.php:77
{
if ( ! @ftp_login($connection, $options->username(), $options->password())) {
throw new UnableToAuthenticate();
}
}
/**
* @param resource $connection
*/
private function enableUtf8Mode(FtpConnectionOptions $options, $connection): void
{
if ( ! $options->utf8()) {
return;
}
$response = @ftp_raw($connection, "OPTS UTF8 ON");
if ( ! in_array(substr($response[0], 0, 3), ['200', '202'])) {
throw new UnableToEnableUtf8Mode(
'Could not set UTF-8 mode for connection: ' . $options->host() . '::' . $options->port()
);
}
}
/**
* @param resource $connection
*/
private function ignorePassiveAddress(FtpConnectionOptions $options, $connection): void
{
$ignorePassiveAddress = $options->ignorePassiveAddress();
if ( ! is_bool($ignorePassiveAddress) || ! defined('FTP_USEPASVADDRESS')) {
return;
}
if ( ! @ftp_set_option($connection, FTP_USEPASVADDRESS, ! $ignorePassiveAddress)) {
throw UnableToSetFtpOption::whileSettingOption('FTP_USEPASVADDRESS');View on GitHub (pinned to b277b5dc3d)
Solutions
- Set 'utf8' => false in FtpConnectionOptions if the server does not support OPTS UTF8 ON.
- Keep utf8 = true only for servers that advertise UTF8 in their FEAT response — verify with an FTP client sending FEAT.
- If UTF-8 filenames matter and the server lacks the option, encode filenames yourself before writing paths.
- Catch UnableToEnableUtf8Mode during adapter warm-up to fail fast with a configuration-specific message.
Example fix
// before
$options = FtpConnectionOptions::lazy('ftp.example.com', '/', FTP_NATIVE, null, 'u', 'p', null, false, true); // utf8: true
new Filesystem(new FtpAdapter($options)); // server replies 500 -> throws
// after (server without UTF8 support)
$options = FtpConnectionOptions::lazy('ftp.example.com', '/', FTP_NATIVE, null, 'u', 'p', null, false, false); // utf8: false Defensive patterns
Strategy: validation
Validate before calling
// Probe server capability once, then build options accordingly $features = ftp_raw($connection, 'FEAT'); $supportsUtf8 = array_any($features ?? [], fn ($l) => str_contains(strtoupper($l), 'UTF8')); $options = FtpConnectionOptions::lazy($host, '/', FTP_NATIVE, null, $user, $pass, null, $ssl, $supportsUtf8);
Try / catch
use League\Flysystem\Ftp\UnableToEnableUtf8Mode;
try {
$filesystem->listContents('/');
} catch (UnableToEnableUtf8Mode $e) {
// server answered something other than 200/202 to OPTS UTF8 ON:
// rebuild adapter with utf8 disabled rather than retrying
$options = FtpConnectionOptions::lazy($host, '/', FTP_NATIVE, null, $user, $pass, null, $ssl, false);
$filesystem = new Filesystem(new FtpAdapter($options));
} Prevention
- Enable utf8 only for servers that advertise it via FEAT.
- Keep FTP connection options per-host in config, not one shared preset.
- If UTF-8 filenames are required on a non-supporting server, transliterate/encode names application-side.
When it happens
Trigger: Constructing FtpAdapter (or first adapter operation that opens a connection) with utf8 enabled against a server that does not advertise/support the UTF8 option (many Windows/IIS or embedded FTP servers return 500 'Command not understood').
Common situations: Copying FtpConnectionOptions tuned for a Linux server to an IIS/appliance FTP endpoint; enabling utf8 defensively 'for unicode filenames' without checking server support; embedded devices (printers, NAS boxes) with minimal FTP implementations.
Related errors
- Metadata can't be parsed from item '$item' , not enough part
- Unable to login/authenticate with FTP
- Could not set passive mode for connection: {host}::{port}
- Unable to get checksum for $path: $reason
- ETag header not available.
AI-assisted analysis of thephpleague/flysystem@b277b5dc3d (2026-08-17).
Data as JSON: /api/errors/65f0be163dfd5eaf.
Report an issue: GitHub.