Fix ‘The Link You Followed Has Expired’ in WordPress

by Fahim

You hit “Install Now” on a 45MB Envato theme zip, wait thirty seconds, and WordPress dumps you onto a blank page with a single unhelpful sentence: The link you followed has expired.

No error code, no log output, just a dead end. Here is what is actually breaking under the hood and how to fix it across Apache, LiteSpeed, Nginx, or straight from the command line.

Close-up view of server configuration settings showing PHP upload and memory limits in a terminal
Close-up view of server configuration settings showing PHP upload and memory limits in a terminal

Why WordPress Throws ‘The Link You Followed Has Expired’

The error message is flat-out misleading. It sounds like your session timed out or you double-clicked an expired form submission, but that is almost never what happened here.

Whenever you submit a form in the WordPress admin, WordPress creates and verifies a security token called a nonce. You can read up on the mechanics in the WordPress wp_verify_nonce documentation.

When you upload an archive via /wp-admin/theme-install.php?upload, the file binary and that nonce travel together in one multipart POST request. If that file exceeds your server’s PHP upload or post limits, PHP aborts the upload mid-flight and dumps the entire $_POST array into the trash.

WordPress still receives the stripped-down request, but because PHP wiped the payload, the _wpnonce field is gone. WordPress looks for the token, finds nothing, assumes the request was forged or expired, and serves you that generic error screen.

Check 1: Did You Upload the Entire Envato Zip Bundle?

Before you touch any server configs, make sure you didn’t upload the wrong zip. I still see developers get burned by this all the time with ThemeForest downloads.

When you click “Download” on ThemeForest, you get two choices: “All files & documentation” or “Installable WordPress file only”.

  • All files & documentation: The kitchen sink. You get the theme, licensing docs, Figma/PSD files, child themes, and nested plugin zips. It usually clocks in between 80MB and 300MB.
  • Installable WordPress file only: Just the actual theme directory containing style.css and functions.php. This is usually 10MB to 30MB.

If you feed WordPress the entire bundle, it will choke immediately on file size. And even if your limits are ridiculously high, WordPress will unpack it, fail to find the core files at the root level, and throw: Fix ‘Theme is Missing the style.css Stylesheet’ in WordPress.

Unzip the master download on your local machine first. Look for the inner archive—usually named themename.zip—and upload that one instead.

Check Current PHP Upload Limits in Site Health

If you’re uploading the right zip and still hitting the error, PHP is dropping your connection. Check what your server is currently enforcing before you start changing values.

Head to Tools > Site Health in your dashboard, click the Info tab, and expand Server.

Look at these four directives:

  • PHP post max size: Often stuck at a default 8M.
  • PHP upload max filesize: Often an abysmal 2M.
  • PHP memory limit: Needs to be at least 256M for bloated themes.
  • PHP max execution time: Usually capped at 30 seconds.

If your theme zip is 32MB and your upload_max_filesize is 2M, PHP terminates the upload before WordPress even gets a chance to inspect it. Let’s bump those numbers.

Fix 1: Adjust Limits in .htaccess (Apache & LiteSpeed)

If you’re on Apache or LiteSpeed (standard cPanel hosting), you can usually override PHP’s runtime limits directly inside your root .htaccess file.

Open the .htaccess file in your WordPress root directory (right alongside wp-config.php) using SFTP, SSH, or your host’s file manager.

Add this block at the very bottom of the file, making sure it sits outside the # BEGIN WordPress and # END WordPress markers:

# Increase PHP upload limits for large themes
php_value upload_max_filesize 64M
php_value post_max_size 64M
php_value max_execution_time 300
php_value max_input_time 300
php_value memory_limit 256M

Save the file and try your upload again. Note that the PHP documentation on upload_max_filesize requires post_max_size to be greater than or equal to upload_max_filesize.

Watch out: If your site immediately throws a 500 Internal Server Error, your host is running PHP via FastCGI or PHP-FPM rather than an Apache module. FastCGI hates php_value in .htaccess. Delete those lines to get your site back online, then move to Fix 2.

Fix 2: Modify php.ini or .user.ini

If you are running PHP-FPM, directives belong in a php.ini or a localized .user.ini file instead of .htaccess.

Check your WordPress root directory over SFTP or terminal. If you see a .user.ini file, edit it. If neither file exists, create a new .user.ini file in that same root folder alongside wp-config.php.

Paste these directives:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300

One catch: changes to .user.ini don’t always take effect instantly. PHP caches these ini files for around 300 seconds (5 minutes). If you have shell access or a cPanel PHP selector, restart the PHP service to flush the cache immediately.

Fix 3: Configure Nginx client_max_body_size and PHP-FPM

If you run an Nginx VPS with PHP-FPM, editing .htaccess does absolutely nothing. You need to adjust settings in both Nginx and your PHP-FPM pool.

Step 1: Update Nginx

Open your site’s server block configuration. On Ubuntu or Debian, that’s typically at /etc/nginx/sites-available/your-site.com.

sudo nano /etc/nginx/sites-available/your-site.com

Inside the server { ... } block, add client_max_body_size:

server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com; client_max_body_size 64M; # remaining configuration...
}

Without this directive, Nginx drops the payload before PHP ever sees it and serves a 413 error instead. We broke down the mechanics of this in our guide to fixing 413 Request Entity Too Large in WordPress on Nginx.

Step 2: Update PHP-FPM

Now open the main php.ini file used by your PHP-FPM pool. For PHP 8.2, that’s here:

sudo nano /etc/php/8.2/fpm/php.ini

Hit CTRL+W in nano, search for these settings, and raise them:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300

Test your Nginx syntax and reload both services:

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm

Fix 4: Bypass the Browser and Install via WP-CLI or SFTP

If you’re stuck on locked-down shared hosting where PHP settings are hard-capped, or if your local internet keeps dropping large POST requests, skip the browser upload entirely.

Option A: Install with WP-CLI

If you have SSH access, using WP-CLI theme install is easily the cleanest solution. It runs through the CLI binary directly on the server, bypassing web server payload caps and execution timeouts.

SCP your theme zip to the server, cd to your WordPress root, and run:

cd /var/www/html
wp theme install /path/to/themename.zip --activate

WP-CLI unzips the file, verifies the headers, drops it into wp-content/themes/, and activates it in a couple of seconds.

Option B: Manual SFTP Extraction

If you don’t have SSH, use an SFTP client like FileZilla or Cyberduck:

  1. Unzip the theme archive locally on your computer. You want the folder that contains style.css and functions.php directly inside it.
  2. Connect to your server over SFTP.
  3. Browse to /wp-content/themes/.
  4. Upload the unzipped folder straight into that directory.
  5. Open your WordPress dashboard, go to Appearance > Themes, and activate it.

Keep in mind that complex Envato themes usually need demo imports and bundled plugins right after activation. Make sure your server doesn’t time out during that step by checking out how to install Envato themes and import demo data without timeouts.

What to Check if the Error Persists

If you’ve raised all your limits to 128M, confirmed you’re using the installable zip, and still see the error, you’re dealing with an edge case.

1. Web Application Firewalls (Cloudflare or ModSecurity)

If your site sits behind Cloudflare, the free tier caps HTTP request body sizes at 100MB. If your theme file is massive, Cloudflare drops the connection before it hits your origin server.

On the host side, an aggressive Apache mod_security rule might flag large form uploads containing bundled PHP scripts or demo importers as suspicious, dropping the request with zero warning.

2. WordPress Autosave and Transients Table Bloat

Rarely, an overloaded database can cause nonce verification queries to time out under heavy write locks. If your options table has accumulated hundreds of thousands of stale transients, clean it up. We covered how to tackle this in our walkthrough on cleaning up bloated wp_options autoload data with WP-CLI.

Frequently Asked Questions

Why does WordPress show ‘The link you followed has expired’ instead of ‘File too large’?

Because PHP intercepts and drops the oversized upload before WordPress code ever boots up. When PHP drops the request, all form inputs—including the security token (_wpnonce)—are lost. WordPress only sees an empty POST request with an invalid nonce, so it defaults to the standard security error screen.

Can I fix this error by editing wp-config.php?

Only partially. Adding define('WP_MEMORY_LIMIT', '256M'); inside wp-config.php increases the memory allocated to WordPress once PHP runs. However, it cannot alter PHP core ini directives like upload_max_filesize or post_max_size, which dictate how the server handles incoming file streams before loading the CMS.

What is the minimum recommended upload limit for ThemeForest themes?

Set both upload_max_filesize and post_max_size to at least 64M (or 128M if the theme includes large video demo assets or slider packages). Set max_execution_time to at least 300 seconds to allow the server enough time to unzip and move assets.

Will updating WordPress overwrite my .htaccess or php.ini changes?

WordPress core updates will not overwrite your custom directives in .htaccess as long as you place your custom rules outside the # BEGIN WordPress and # END WordPress tags. Custom php.ini and .user.ini files are completely independent of WordPress updates and will remain intact.

Next Steps

Once your theme uploads cleanly, don’t dial your server execution limits back down to the bare minimums. Heavy themes rely on bundled plugins like Slider Revolution and Elementor that demand hefty memory and execution budgets during setup.

If your theme chokes while pulling in sample layouts or media assets, check out our guide on importing Envato demo data without timeouts to get the rest of your site running smoothly.

all_in_one_marketing_tool