thephpleague/flysystem · error · UnableToMakeConnectionPassive

Could not set passive mode for connection: {host}::{port}

Error message

Could not set passive mode for connection: {host}::{port}

What it means

FtpConnectionProvider::makeConnectionPassive() calls ftp_pasv() with the 'passive' option value; if the FTP extension reports failure, UnableToMakeConnectionPassive is thrown with 'Could not set passive mode for connection: host::port'. ftp_pasv only sets the transfer-mode preference, but it fails when the connection is broken or the server rejects the PASV setup during handshake, and Flysystem treats it as fatal.

Source

Thrown at src/Ftp/FtpConnectionProvider.php:105

    {
        $ignorePassiveAddress = $options->ignorePassiveAddress();

        if ( ! is_bool($ignorePassiveAddress) || ! defined('FTP_USEPASVADDRESS')) {
            return;
        }

        if ( ! @ftp_set_option($connection, FTP_USEPASVADDRESS, ! $ignorePassiveAddress)) {
            throw UnableToSetFtpOption::whileSettingOption('FTP_USEPASVADDRESS');
        }
    }

    /**
     * @param resource $connection
     */
    private function makeConnectionPassive(FtpConnectionOptions $options, $connection): void
    {
        if ( ! @ftp_pasv($connection, $options->passive())) {
            throw new UnableToMakeConnectionPassive(
                'Could not set passive mode for connection: ' . $options->host() . '::' . $options->port()
            );
        }
    }
}

View on GitHub (pinned to b277b5dc3d)

Solutions

  1. Open the server's passive port range (e.g. 50000-51000) in the FTP server config AND the firewall, and set matching PassivePortRange on the server.
  2. If the server/network requires active mode, set 'passive' => false in FtpConnectionOptions.
  3. Verify basic PASV transfers with an FTP CLI client from the same host/network namespace to isolate app vs environment.
  4. Catch UnableToMakeConnectionPassive and retry once — transient control-connection drops can surface here.

Example fix

// before
$options = FtpConnectionOptions::lazy('ftp.example.com', '/', FTP_NATIVE, null, 'u', 'p', null, true /* passive */);
$filesystem->read('file.txt'); // ftp_pasv fails -> throws

// after (active mode environment)
$options = FtpConnectionOptions::lazy('ftp.example.com', '/', FTP_NATIVE, null, 'u', 'p', null, false /* active */);
Defensive patterns

Strategy: retry

Validate before calling

// No in-code pre-check possible for ftp_pasv, but you can pre-flight connectivity:
// ensure the server's passive port range is reachable from the app host
$socket = @fsockopen($host, 50000, $errno, $errstr, 3); // first port of the declared range
if ($socket === false) {
    // passive data channel blocked: fix firewall/NAT before runtime failures
}
fclose($socket);

Try / catch

use League\Flysystem\Ftp\UnableToMakeConnectionPassive;

$maxAttempts = 2;
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
    try {
        return $filesystem->read($path);
    } catch (UnableToMakeConnectionPassive $e) {
        if ($attempt === $maxAttempts) {
            // persistent: likely firewall/active-mode mismatch — switch strategy, don't loop
            $options = FtpConnectionOptions::lazy($host, '/', FTP_NATIVE, null, $user, $pass, null, false);
            $filesystem = new Filesystem(new FtpAdapter($options));
        }
    }
}

Prevention

When it happens

Trigger: First file operation after connect when passive = true and the server/firewall interferes with the PASV command (some servers reject PASV before authentication or when data connections are blocked); the control connection dropped between login and pasv; ftp_pasv returning false on servers behind broken NAT.

Common situations: Firewalls between app and FTP server blocking the passive data port range; servers that require active mode (passive = false) but the option was left true; containerized apps where the FTP module cannot negotiate data connections.

Related errors


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