You click Appearance > Themes > Add New > Upload Theme, select the zip file you just downloaded from ThemeForest, hit Install Now, and wait. After twenty seconds of spinning, you get dumped onto a stark white screen with a single sentence: “The link you followed has expired.”
No stack trace, no error code, just pure vagueness. It’s one of the most frustrating screens in WordPress. Before you tear your hair out or open a support ticket with the theme author, know that your theme isn’t corrupt. Nine times out of ten, you either uploaded the master documentation archive by accident or tripped over PHP’s default file upload ceilings.
Here’s what’s actually happening under the hood and how to fix it in a few minutes.

Why WordPress Throws “The Link You Followed Has Expired”
Behind the scenes, WordPress uses security tokens called nonces to verify that form submissions come from legitimate sessions. When you upload a theme zip, WordPress generates a nonce and expects to validate it once the file lands on the server.
If your upload takes too long or exceeds your server’s payload ceiling, the PHP worker process dies mid-transfer. When WordPress tries to check the nonce on a truncated or timed-out request, the token is invalid or missing. Lacking a better catch-all, WordPress serves its default fallback error: The link you followed has expired.
The culprit almost always comes down to stingy PHP runtime defaults:
- upload_max_filesize: Defaults to 2M or 8M on fresh installs or budget shared hosts.
- post_max_size: Must be larger than
upload_max_filesize. If your theme is 25MB and this is set to 8MB, the server drops the entire POST request without a peep. - max_execution_time: Often capped at 30 seconds. On a typical residential upload speed, a 40MB zip file will easily time out before it ever reaches
/tmp. - memory_limit: Unzipping and staging large asset bundles eats RAM. If PHP runs out of headroom, the script crashes immediately.
Check If You Uploaded the Full Envato Package
Before you start digging into config files, check the actual file you tried to upload. This trips up almost everyone at least once.
On ThemeForest’s downloads tab, clicking the green download button gives you two choices: “All files & documentation” and “Installable WordPress file only”.
If you picked “All files & documentation”, you downloaded a master bundle. That zip contains licensing txt files, documentation PDFs, demo XML exports, design assets, child themes, and the actual theme archive nested inside. The whole thing can easily weigh 50MB to 150MB.
Unzip that master archive on your machine. If you see folders named Documentation, Licensing, or another zip file sitting inside it, stop right there. You want the inner zip—usually named something like flatsome.zip or avada.zip. If you try uploading the parent archive, you’ll either hit this expired link screen or end up with an error saying the theme is missing style.css.
If you know for a fact you’re uploading the clean installable zip and still see this error, your server limits are simply too low. Let’s bump them.
Method 1: Update .htaccess (Apache & LiteSpeed)
If you’re running Apache or LiteSpeed with mod_php, the fastest route is dropping directives straight into your root .htaccess file. Connect via SFTP or your host’s file manager, go to your WordPress root (where wp-config.php sits), and open .htaccess.
Add these directives right below the # END WordPress block:
php_value upload_max_filesize 64M
php_value post_max_size 64M
php_value max_execution_time 300
php_value max_input_time 300Save it and try uploading the theme again.
If your site instantly throws a 500 Internal Server Error, don’t panic. That just means your host runs PHP via FastCGI or PHP-FPM, which doesn’t allow php_value flags in .htaccess. Delete those lines right away to clear the 500, and head over to Method 2.
Method 2: Update php.ini or .user.ini (PHP-FPM & Nginx)
Most modern production stacks—especially VPS setups, RunCloud, SpinupWP, or modern managed hosts—run PHP-FPM. Here, custom directives belong in .user.ini or the server’s global php.ini.
In your WordPress root directory (next to wp-login.php), look for a file named .user.ini. If it doesn’t exist, create it. Add these lines:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300One catch with .user.ini: unlike .htaccess, which Apache parses on every hit, PHP-FPM caches .user.ini values. The default cache TTL (user_ini.cache_ttl) is 300 seconds (5 minutes). If the upload doesn’t work right away, wait five minutes or reload PHP-FPM manually if you have SSH/root access:
sudo systemctl reload php8.2-fpmRemember to change php8.2-fpm to whatever PHP version you’re actually running (like 8.1 or 8.3). If you’re on cPanel or a custom control panel, check our guide on how to increase the maximum upload file size directly via your host’s UI.
Method 3: Define Limits in wp-config.php
If your hosting setup locks down custom INI files, you can try raising runtime limits in wp-config.php.
Fair warning: this won’t always work for upload_max_filesize or post_max_size because PHP locks those in during request startup, before WordPress code ever executes. But bumping the memory limit and execution time here will often prevent the worker process from dying mid-extract.
Open wp-config.php and paste these right before the line reading /* That's all, stop editing! Happy publishing. */:
@ini_set('upload_max_filesize', '64M');
@ini_set('post_max_size', '64M');
@ini_set('max_execution_time', '300');
define('WP_MEMORY_LIMIT', '256M');Check the official WordPress wp-config documentation if you’re not sure where to drop custom constants safely.
Method 4: Install via WP-CLI or SFTP (Zero Limits)
If your shared host has locked down all INI overrides and you just want the theme installed right now, skip the browser upload entirely. Browser uploads must route through the HTTP POST pipeline; uploading files directly completely bypasses those limits.
Option A: Install via WP-CLI
If you have SSH access, WP-CLI is hands down the cleanest way to handle stubborn themes. Run the WP-CLI theme install command pointing directly to the zip file:
wp theme install /path/to/my-theme.zip --activateBecause WP-CLI runs via the command-line PHP binary (CLI), it operates without web server POST limits or browser timeouts. It unzips straight into wp-content/themes/ and activates it in seconds.
Option B: Upload via SFTP
If you don’t have SSH or prefer an SFTP client like FileZilla:
- Unzip the installable theme archive on your local computer so you have a regular folder (e.g.,
/salient/or/flatsome/). - Connect to your server over SFTP and open
/wp-content/themes/. - Upload that entire unzipped theme folder directly into
/wp-content/themes/. - Head back to your WordPress dashboard under Appearance > Themes. The theme will be sitting right there, ready to activate.
Verify Your Active Limits in WordPress
Don’t guess whether your changes actually registered. WordPress has a built-in diagnostic tool that reads your live environment values directly.
- Head to Tools > Site Health in your dashboard.
- Click the Info tab.
- Open the Server accordion.
Look for these numbers:
- PHP post max size: Should show
64Mor higher. - PHP upload max filesize: Should match or be lower than post max size (at least
64M). - PHP memory limit: Should be
256Mor higher for heavy commercial themes. - PHP time limit: At least
300.
If you want to understand how directive precedence works across web servers and CLI, dig into the PHP official manual on core php.ini directives.
Frequently Asked Questions
Why did this error happen only with my Envato theme and not free repository themes?
Themes from the official WordPress directory don’t get uploaded through your browser. WordPress downloads them directly from its own API servers using background cURL requests. Marketplace themes like those on Envato require you to push the entire archive from your local machine through an HTTP POST request, which runs headfirst into whatever upload limits your host configured.
I raised my limits, but the error persists. What else causes this?
If Site Health confirms you have 64M+ limits and you’re still hitting this error, your web server or reverse proxy is dropping the connection before PHP ever sees it. If you run Nginx (either standalone or as a reverse proxy in front of Apache), check client_max_body_size. By default, Nginx caps client bodies at 1MB. Open /etc/nginx/nginx.conf, set client_max_body_size 64M; inside your http or server block, and reload Nginx.
Can I leave these high limits active permanently?
Yes. 64MB uploads and a 256MB memory limit are standard practice for modern WordPress sites. You’ll need these anyway when importing demo content, running updates, or uploading hi-res media assets.
Next Steps
Once your theme is active, don’t rush straight into importing massive demo packs without knowing what baggage they pull in. Commercial themes love bundling heavyweight sliders, bloated page builders, and dozens of font weights. Check out our guide on how to dequeue unused scripts and styles in Envato themes to keep things lean, and read through how to audit WordPress themes on Envato before you push anything to production.

