Fix ‘The Link You Followed Has Expired’ in WordPress

by Fahim

You hit “The link you followed has expired” the second you click “Install Now” on a 35MB theme zip in your WordPress dashboard. I run into this all the time when spinning up staging sites or testing marketplace themes packed with demo content and bundled plugins.

WordPress gives you zero helpful context here—just a plain white screen, one useless sentence, and a dead-end link to reload. What actually happened is simple: your server choked on the upload request before finishing it. Because the PHP execution or POST limits kicked in, the CSRF security token (the nonce) expired before WordPress could unpack the archive.

Fix 'The Link You Followed Has Expired' in WordPress
Fix 'The Link You Followed Has Expired' in WordPress

Why WordPress Throws ‘The Link You Followed Has Expired’

WordPress protects form submissions with nonces—one-time security tokens verifying that a request came from an authenticated user. When you upload a theme via Appearance > Themes > Add New, WordPress creates a nonce and streams the file to a temporary directory.

If your zip file exceeds your server’s default PHP limits, the server cuts the connection mid-stream. The script never finishes processing the payload, WordPress assumes the token timed out or was tampered with, and you get the generic “expired link” error.

Four PHP directives cause nearly all of these failures:

  • upload_max_filesize: Max file size for a single upload (often stuck at 2MB on default setups).
  • post_max_size: Total payload limit for an HTTP POST request (must be larger than upload_max_filesize).
  • max_execution_time: How long a script can run before getting killed (often 30 seconds).
  • max_input_time: How long a script has to parse input data like file uploads.

Check Your Current PHP Limits in WordPress Site Health

Before touching config files, check what limits your server is actually enforcing. You don’t need a custom phpinfo() script for this.

  1. Open your WordPress dashboard.
  2. Go to Tools > Site Health.
  3. Click the Info tab, then expand Server and Media Handling.

Check Upload max filesize and PHP post max size. If your theme archive is 28MB and your upload_max_filesize is 2M or 8M, there’s your problem. If you run into write permission errors next, check our guide on how to fix ‘Upload: Failed to Write File to Disk’ in WordPress.

Fix 1: Update .htaccess (Apache & LiteSpeed)

If you’re running Apache or OpenLiteSpeed, editing your root .htaccess file is usually the fastest fix. It sits right in your WordPress root directory next to wp-config.php.

Open .htaccess via SFTP, SSH, or your host’s file manager, and add these lines right below the closing # END WordPress line:

# Custom PHP Upload Limits for WordPress 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 and try uploading again. If your site throws a 500 Internal Server Error immediately after saving, your host runs PHP via CGI/FastCGI, which rejects php_value directives in .htaccess. Remove those lines and jump to Fix 2.

Fix 2: Modify php.ini or .user.ini (Nginx & FastCGI)

For Nginx or Apache setups running PHP-FPM, you need to define these directives in a php.ini or .user.ini file in your WordPress root directory (typically /public_html/ or /var/www/html/).

Create or edit .user.ini in your root directory and add:

; Increase file upload and execution limits
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300

Per the PHP core directives documentation, post_max_size must be equal to or larger than upload_max_filesize. If you bump upload size to 64M but leave post size at 8M, anything over 8MB will still silently fail.

Keep in mind that PHP-FPM caches .user.ini files for a few minutes. If you have root access to your VPS, restart PHP-FPM to apply the changes right away:

# Restart PHP 8.2 FPM on Ubuntu/Debian
sudo systemctl restart php8.2-fpm # Or restart PHP 8.3 FPM
sudo systemctl restart php8.3-fpm

Fix 3: Define Limits in wp-config.php

If you can’t edit server configs directly, you can raise execution limits inside wp-config.php. While runtime functions like ini_set() can’t change upload_max_filesize during script execution, bumping your memory and execution times directly in WordPress often prevents mid-transfer timeouts.

Open wp-config.php and paste this right above the /* That's all, stop editing! Happy publishing. */ line:

// Increase memory and execution time
@ini_set('max_execution_time', '300');
@ini_set('max_input_time', '300');
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');

If you’re installing themes packed with hefty demo datasets, check our guide on how to install an Envato WordPress theme and import demo content so you don’t hit memory limits during database imports.

Fix 4: Check for the ‘Nested Zip’ Theme Bundle Gotcha

A surprising number of “expired link” errors have nothing to do with server configs. When you hit “Download All files & documentation” on ThemeForest or Envato, you get a massive master zip containing docs, design files, license keys, plugins, and the actual theme archive nested inside.

These bundles can easily run 60MB to 200MB. Uploading that master file causes two headaches:

  1. It blows past your server’s POST limits.
  2. Even if the upload finishes, WordPress can’t find style.css in the root folder and fails. If that happens, see how to fix ‘The theme is missing the style.css stylesheet’ error.

Here’s my standard sanity check before uploading:

  • Extract the downloaded marketplace zip locally.
  • Find the internal zip named specifically after the theme (e.g., theme-name.zip).
  • Inspect the inner zip to make sure style.css and functions.php sit at its root.
  • Upload only that inner zip file.

If you’re evaluating themes, you can also test ThemeForest WordPress themes for bloat before buying to steer clear of messy, bloated packages.

Fix 5: Bypass the Web Uploader with WP-CLI or SFTP

If you have terminal or SFTP access, skip fighting the browser uploader entirely. Bypassing HTTP POST removes browser timeout issues from the equation.

Method A: Install via WP-CLI

If you have SSH access, use WP-CLI theme install. It bypasses web server payload restrictions and runs directly in your CLI environment:

# Navigate to your WordPress root
cd /var/www/html # Install the theme from a local zip file path
wp theme install /path/to/my-theme.zip --activate # Or install directly from a remote URL
wp theme install https://example.com/downloads/my-theme.zip --activate

You’ll see real-time output right in your terminal:

Unpacking the package...
Installing the theme...
Theme installed successfully.
Activating 'my-theme'...
Success: Switched to 'My Theme' theme.

Method B: Manual SFTP Upload

If you don’t have WP-CLI, extract the theme zip locally. You’ll end up with a folder named after the theme (e.g., astra or custom-theme).

  1. Connect to your server via FileZilla or Cyberduck.
  2. Navigate to /wp-content/themes/.
  3. Drop the unzipped theme folder directly into that directory.
  4. Head back to your admin dashboard at Appearance > Themes.
  5. Hit Activate on the new theme.

Verify Your New Upload Limits

After updating your config files, verify the changes took effect globally. Go back to Tools > Site Health > Info > Media Handling.

Make sure Upload max filesize matches what you set in .htaccess or .user.ini (like 64 MB). If Site Health still shows 2 MB, your host is likely enforcing a hard override at the server level. At that point, either reach out to support or stick with SFTP and WP-CLI.

Frequently Asked Questions

Does ‘The link you followed has expired’ happen with plugin uploads too?

Yes. The exact same mechanism applies when uploading plugins under Plugins > Add New > Upload Plugin. Heavy plugins like page builders regularly top 15MB. The exact same fixes—raising limits in .user.ini or running wp plugin install—will sort it out.

Why didn’t editing functions.php fix the upload error?

Adding @ini_set('upload_max_filesize', '64M'); to functions.php won’t work because the theme isn’t active yet. Even on active themes, PHP doesn’t let you adjust upload_max_filesize at runtime via ini_set() because uploads are handled before your theme’s code even loads.

What is the recommended PHP limit for modern WordPress sites?

For modern WordPress setups, set upload_max_filesize = 64M, post_max_size = 64M, memory_limit = 256M, and max_execution_time = 300. That gives you plenty of headroom for large theme uploads, bulk imports, and background image resizing without draining server resources.

Could a security plugin cause this error?

Yes, though it’s less common. If your file size is well within limits and the error hits instantly, an aggressive security plugin or Web Application Firewall (WAF) might be stripping the _wpnonce token from the multipart POST request. Temporarily disable the firewall to test the upload.

Once your theme is installed and running, make sure your server delivers assets quickly. Check out our walkthrough on configuring CDN edge cache rules for WordPress to optimize frontend delivery.

all_in_one_marketing_tool