Ffile2fix
Sign in Get started

How to Fix a .htaccess 500 Internal Server Error (Step by Step)

You save a small change to .htaccess, refresh the page, and the whole site shows 500 Internal Server Error. It looks serious, but it almost never is. Apache and LiteSpeed read .htaccess on every request, so a single bad line takes down every page at once β€” and the same single line is usually the whole fix.

This guide walks through the fastest way to confirm .htaccess is the cause, find the exact line that breaks it, and fix the six mistakes behind almost every case.

Step 1: Confirm .htaccess is really the cause (30 seconds)

Rename the file instead of deleting it. In your hosting file manager or FTP client, rename .htaccess to .htaccess-off, then reload the site.

  • Site loads (maybe with broken pretty URLs): the problem is inside .htaccess. Keep reading.
  • Still a 500 error: the cause is elsewhere β€” usually a PHP fatal error, wrong file permissions, or a memory limit. Check the PHP error log instead (our PHP Error Stack Analyzer reads it for you).

Rename the file back once you know. Without it, WordPress permalinks, HTTPS redirects and any security rules stop working.

Step 2: Read the error log β€” it names the line

A 500 error page hides the real message on purpose. The server's error log does not. On most hosts you'll find it in the control panel (hPanel, cPanel: Errors or Error Logs), or as an error_log file next to your site files. Look for lines like these:

/home/user/public_html/.htaccess: Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration
/home/user/public_html/.htaccess: RewriteRule: bad flag delimiters
/home/user/public_html/.htaccess: <IfModule takes one argument, Container for directives based on existence of specified modules
/home/user/public_html/.htaccess: Option Indexes not allowed here

Each one maps straight to a fix below. If you can't find a log, use the bisect method in Step 4.

Step 3: Fix the six most common .htaccess mistakes

1. A typo in a directive name

Invalid command 'RewriteEgine' means exactly what it says. Directives are not forgiving about spelling. Compare carefully: RewriteEngine, RewriteCond, RewriteRule, ErrorDocument, Header.

2. A module that isn't installed or enabled

If the directive is spelled correctly but still "invalid", the module behind it isn't loaded β€” for example Header needs mod_headers and ExpiresActive needs mod_expires. Wrap optional blocks so they're skipped safely when the module is missing:

<IfModule mod_headers.c>
  Header set X-Content-Type-Options "nosniff"
</IfModule>

Do not wrap your core rewrite rules this way. If mod_rewrite is missing, you want to know β€” otherwise your URLs quietly stop working.

3. Unclosed or mismatched blocks

Every <IfModule>, <Files> and <FilesMatch> needs a matching closing tag, and the opening tag needs exactly one argument. A common copy-paste accident:

<IfModule mod_rewrite.c      ❌ missing >
<IfModule mod_rewrite.c>     βœ…
...
</IfModule>                  βœ… every block closed

4. Bad RewriteRule flags

Flags go in square brackets, comma-separated, with no spaces: [L,R=301]. [L, R=301] or (L) triggers "bad flag delimiters". Also check for smart quotes pasted from a blog or Word document β€” β€œ and ” are not ".

5. Directives your host doesn't allow

not allowed here means the server's main config (AllowOverride) blocks that directive in .htaccess. Shared hosts commonly block Options and some php_value lines. Remove the line, or move PHP settings to a .user.ini file / your host's PHP settings page:

# Instead of this in .htaccess (breaks on PHP-FPM / LiteSpeed hosts):
php_value memory_limit 256M

# Put this in .user.ini:
memory_limit = 256M

6. Redirect loops that look like a 500

Two rules redirecting to each other (HTTP→HTTPS plus a plugin doing the same, or www→non-www fighting a CDN setting) can end in "too many redirects" or an internal error after the server hits its rewrite limit. Keep exactly one place that handles each redirect. A safe HTTPS + non-www pair:

RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]

If your site sits behind Cloudflare with "Flexible" SSL, %{HTTPS} is always off at your server, which causes an endless loop. Switch Cloudflare to "Full" or check X-Forwarded-Proto instead.

Step 4: No log? Find the bad line by halving the file

  1. Make a copy of the full file as a backup.
  2. Delete (or comment out with #) the bottom half. Reload.
  3. If the site works, the bad line is in the half you removed. If not, it's in the half you kept.
  4. Repeat on the guilty half until one line or one block is left.

Even a 200-line file takes about eight rounds. Comment out whole <IfModule> blocks together so you never leave one half-open.

Step 5: Rebuild a clean default (WordPress)

If the file is a mess of old plugin rules, start from the standard WordPress block and add back only what you need:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Then go to Settings β†’ Permalinks and click Save once. WordPress rewrites its own section correctly.

Check your file before it goes live

The fastest way to avoid the next 500 is to check the file before you upload it. Paste it into the free .htaccess Validator. It flags unclosed blocks, bad flags, smart quotes and directives that commonly fail on shared hosting, so you fix them before visitors see an error.

Quick checklist

  • Rename .htaccess to confirm it's the cause.
  • Read the error log β€” it names the broken line.
  • Check spelling, missing modules, unclosed blocks and flag syntax.
  • Move php_value lines to .user.ini.
  • Keep one place for each redirect.
  • Validate the file before every upload.

Try the related tools

More guides

File Conversion

How to Convert JSON, CSV, XML, Markdown, and Images Privately

Choose the right converter for structured data, documents, or images β€” and learn why browser-only conversion is safer for sensitive files.

Security

How to Share a Repaired File Without Exposing Your Server

A safe handoff checklist for repaired files: inert storage names, forced downloads, expiry, access expectations, and the mistakes to avoid.

SEO

Technical SEO Checklist for Online Tool Pages

How tool directories can earn useful search traffic without creating thin pages: clear URLs, intent-led copy, schema, internal links, and honest indexing.

ZIP & Archives

How to Fix a Corrupted ZIP File: 5 Methods That Actually Work

From a quick integrity check to multi-pass deep repair β€” a practical, no-nonsense guide to recovering a damaged ZIP archive, matched to what actually broke.

Code Repair

How to Fix Broken JSON: Common Errors and Quick Repairs

Trailing commas, unescaped quotes, single quotes, unbalanced brackets β€” the five JSON errors that cause almost every parsing failure, and how to fix them fast.

Debugging

Common PHP Fatal Errors Explained (and How to Actually Fix Them)

Undefined function, class not found, memory exhausted, execution time exceeded β€” what these PHP fatal errors really mean, and how to read a stack trace correctly.

Security & Config

.env File Best Practices: How to Validate and Secure Your Environment Variables

Silent syntax errors, missing variables, and accidentally committed secrets β€” a practical audit checklist for your .env file before it causes a production incident.

WordPress

How to Read Your WordPress debug.log (and Actually Fix What It Tells You)

How to turn on WordPress debug logging, tell fatal errors from harmless deprecation notices, and identify exactly which plugin or theme is actually responsible.