Ffile2fix
Sign in Get started

How to fix WordPress posts and pages returning 404

Not Found
The requested URL /sample-page/ was not found on this server.
Apache/2.4.58 (Ubuntu) Server at example.com Port 443

WordPress uses pretty permalinks like /sample-page/, which only work if the web server sends every unknown URL to index.php. If the .htaccess rewrite rules are missing, mod_rewrite is off, AllowOverride blocks .htaccess, or Nginx lacks a try_files rule, the server returns 404 before WordPress runs.

Also appears as: 404 Not Found nginx · Page not found (theme 404 page) on every post except the homepage · The requested URL was not found on this server. (after migration)

Common causes

  • The .htaccess file is missing or lacks the WordPress rewrite block
  • Apache mod_rewrite is not enabled
  • AllowOverride None in the Apache vhost, so .htaccess is ignored
  • Nginx server block missing try_files $uri $uri/ /index.php?$args;
  • Rewrite rules in the database were not flushed after a migration or plugin change
  • The site moved to a subfolder but RewriteBase was not updated

How to fix it

  1. Re-save permalinks. Go to Settings > Permalinks and click Save Changes without changing anything. This flushes rewrite rules and tries to rewrite .htaccess.
  2. Restore the .htaccess block. Make sure the WordPress root has a .htaccess with the standard # BEGIN WordPress block. Create it if missing, with permissions 644.
  3. Enable mod_rewrite and AllowOverride. On Ubuntu run sudo a2enmod rewrite. In the vhost's <Directory> for the site set AllowOverride All (or at least FileInfo), then run apachectl configtest and reload Apache.
  4. Add try_files on Nginx. Nginx ignores .htaccess. In the server block add location / { try_files $uri $uri/ /index.php?$args; }, then run nginx -t and reload.
  5. Check RewriteBase for subfolders. If WordPress is in /blog/, use RewriteBase /blog/ and RewriteRule . /blog/index.php [L] in .htaccess.

Default WordPress .htaccess block (site in web root)

# BEGIN WordPress
<IfModule mod_rewrite.c>
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]
</IfModule>
# END WordPress

How to stop it happening again

  • Include .htaccess (a hidden file) when migrating sites
  • Add the Nginx try_files rule to every WordPress server block
  • Re-save permalinks after migrations and plugin changes
  • Keep custom rules outside the # BEGIN/END WordPress markers

Frequently asked questions

Why does the homepage work but other pages fail?

The homepage is served by index.php directly. All other pretty URLs need rewrite rules to reach index.php.

Does switching to Plain permalinks fix it?

Plain links like ?p=123 work without rewrites, but they change your URLs and hurt SEO. Fix the server rules instead.

Saving permalinks did not create .htaccess. Why?

WordPress could not write the file, usually due to permissions or ownership. Create .htaccess manually with the block above and set it to 644.