WordPress auto update ‘Unable to locate WordPress Content directory’ or ‘Could not copy file’ fix
February 4, 2012
WordPress is a great way to get a website up and running quickly and the sheer number of plugins and themes means that you can do a lot with it. The downside to this is that both Worpress core and your plugins and themes need updating quite often. WordPress provides an interface to auto update itself by using the FTP details of your hosting but many people get errors such as 'Unable to locate WordPress Content directory (wp-content)' or 'Could not copy file …' when doing this and there are a lot of 'fixes' suggested online (see http://wordpress.org/support/topic/cannot-find-content-directory-wp-content).
The truth is, there is no one single fix for the problem. Sometimes changing the permissions of the WordPress site will sort the problem out, but quite often I see blog posts) where the problem still persists.
I had the same problem on many of the sites we host at work and I spend a few hours getting to the bottom of it. We set permissions on our hosting to be quite restrictive and discourage the use of setting directory permissions as 0777 as it can be vulnerable to exploits. We set files as 0644 and directories at 0754, with writeable folders as 0775, Files and directories are owned by a user and are in the same group as the web server. I tried changing the permissions, even going as far as setting the public_html directory to 0777 (temporarily) and yet the WordPress Upgrade would fail.
I fired up my IDE and debugger (Netbeans and Xdebug) and stepped through the WordPress code line by line to identify where it was failing to complete the update and soon discovered it was failing when listing a directory using PHP's ftp_nlist() function. This would return as boolean false, indicating there was an issue. Just before this happens, the WordPress code sets FTP passive mode to boolean true and this is where the problem was being caused.
The cause was down to a configuration in the FTP server running on our hosts. We use Masquerading to provide the external IP address of the server when switching to passive mode but as the connection was from localhost, this was causing passive mode to fail. A simple configuration change fixed the issue for us.
If you don't have root access on your hosts server you can fix this by editing wp-admin/includes/class-wp-filesystem-ftpext.php and changing the FTP passive mode to false on line 84:
~$: vi wp-admin/includes/class-wp-filesystem-ftpext.php +84 83 //Set the Connection to use Passive FTP 84 @ftp_pasv( $this->link, false ); # was @ftp_pasv( $this->link, true);
Note that this will be overwritten when you upgrade WordPress the next time.
Although this is a mis-configuration in the FTP server it would be nice if there was an option in WordPress to choose passive mode or not. There is a patch and a bug report on the WordPress Trac (see http://core.trac.wordpress.org/ticket/7940) but this was closed as the developers of WordPress chose to force passive mode to 'on'.