How to fix 404 error on all pages except homepage in WordPress

This article explains how to fix a common WordPress issue where the homepage loads correctly but all other pages, posts, and links return a 404 Not Found error.

Symptoms

  • The WordPress homepage loads correctly.
  • All other pages, posts, categories, and links return a 404 error.
  • The problem occurs after a migration, hosting change, or modification to the .htaccess file.

Cause

WordPress uses the .htaccess file to handle friendly URLs (permalinks). When this file doesn't exist, is empty, or is missing the necessary rewrite directives, the server cannot properly redirect requests to WordPress's index.php file.

Solution

Step 1: Restore WordPress Directives in .htaccess

Access your site files using your control panel's File Manager (cPanel or DirectAdmin) or via FTP.

Locate the .htaccess file in the root of your WordPress installation (where wp-config.php is located).

Note: The .htaccess file is a hidden file. In the File Manager, enable the option to show hidden files.

If the file doesn't exist, create it. Then add or replace the content with the following basic WordPress directives:

# BEGIN WordPress

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

Save the file.

Step 2: Verify File Permissions

Make sure the .htaccess file has the correct permissions:

  • Recommended permissions: 444 (read-only)
  • Owner: your hosting user

In cPanel or DirectAdmin, you can change permissions by right-clicking the file and selecting "Permissions" or "Change Permissions".

Step 3: Verify the Problem is Resolved

Visit any page or post on your site. If everything works correctly, the problem is resolved.

WordPress in a Subdirectory

If WordPress is installed in a subdirectory (e.g., yourdomain.com/blog/), modify RewriteBase and the last rule:

# BEGIN WordPress

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]

# END WordPress

Replace /blog/ with your subdirectory name.

Directive Explanation

Directive Function
RewriteEngine On Enables the URL rewriting engine.
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] Preserves the HTTP authorization header for the REST API.
RewriteBase / Defines the base for rewrite rules.
RewriteRule ^index\.php$ - [L] If the request is for index.php, do nothing else.
RewriteCond %{REQUEST_FILENAME} !-f Condition: the requested file doesn't physically exist.
RewriteCond %{REQUEST_FILENAME} !-d Condition: the requested directory doesn't physically exist.
RewriteRule . /index.php [L] Redirect all requests that meet the conditions to index.php.

Troubleshooting

Error Persists After Adding Directives

  • Verify that the .htaccess file is in the WordPress root (same directory as wp-config.php).
  • Confirm that the directives are correctly copied, without extra spaces or characters.
  • Contact your hosting provider to verify that the mod_rewrite module is enabled.

The .htaccess File Gets Overwritten or Modified

If the .htaccess file gets overwritten after adding the directives, this may indicate:

  • A plugin interfering: Some caching, security, or SEO plugins modify .htaccess. Review recently installed plugins or temporarily deactivate them to identify the culprit.
  • Malware on the site: Malware frequently modifies .htaccess to inject malicious redirects. Scan your site for infected files and review access logs for suspicious activity.

References