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

  1. Set 'utf8' => false in FtpConnectionOptions if the server does not support OPTS UTF8 ON.
  2. Keep utf8 = true only for servers that advertise UTF8 in their FEAT response — verify with an FTP client sending FEAT.
  3. If UTF-8 filenames matter and the server lacks the option, encode filenames yourself before writing paths.
  4. 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

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


AI-assisted analysis of thephpleague/flysystem@b277b5dc3d (2026-08-17). Data as JSON: /api/errors/65f0be163dfd5eaf. Report an issue: GitHub.