{"id":8,"date":"2026-06-27T00:00:00","date_gmt":"2026-06-27T00:00:00","guid":{"rendered":"http:\/\/\/var\/www\/html\/?p=8"},"modified":"2026-07-21T01:02:30","modified_gmt":"2026-07-21T01:02:30","slug":"apache-htaccess-redirect-loop-500-internal-server-error","status":"publish","type":"post","link":"https:\/\/butitworkedlocal.com\/apache-htaccess-redirect-loop-500-internal-server-error\/","title":{"rendered":"Resolving Apache .htaccess Redirect Loop 500 Internal Server Error"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>Fix Apache .htaccess redirect loops causing 500 errors. Learn to troubleshoot mod_rewrite rules, canonical URLs, and SSL configurations to restore site access quickly.<\/strong><\/p>\n\n\n<p>A &quot;500 Internal Server Error&quot; originating from an <code>.htaccess<\/code> redirect loop is a common, yet frustrating, issue for web administrators. It typically signifies a misconfigured <code>mod_rewrite<\/code> rule that continuously redirects a request, causing the Apache server to exceed its internal redirect limit and eventually fail. This guide will walk you through diagnosing and resolving these persistent redirect loops, ensuring your website serves content correctly.<\/p>\n<h3>Symptom &amp; Error Signature<\/h3>\n<p>When an Apache <code>.htaccess<\/code> redirect loop occurs, users will typically encounter one of the following in their web browser:<\/p>\n<ul>\n<li><strong>HTTP 500 Internal Server Error:<\/strong> A generic error page indicating a server-side problem.<\/li>\n<li><strong>ERR_TOO_MANY_REDIRECTS:<\/strong> Some browsers, like Chrome, explicitly report that the page isn&#039;t redirecting properly.<\/li>\n<li><strong>&quot;This page isn&#039;t working&quot; \/ &quot;Firefox has detected that the server is redirecting the request for this address in a way that will never complete.&quot;<\/strong>: Similar messages indicating a browser-level redirect limit was hit.<\/li>\n<\/ul>\n<p>The definitive proof of a redirect loop resides in your Apache error logs. You&#039;ll typically find an entry similar to this:<\/p>\n<pre><code class=\"language-log\">[Sat Jun 27 10:30:00.123456 2026] [core:error] [pid 12345:tid 123456789] [client 192.168.1.100:54321] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use &#039;LimitInternalRecursion&#039; to increase the limit if necessary. Use &#039;LogLevel Debug&#039; to get a backtrace.\n[Sat Jun 27 10:30:00.123456 2026] [core:error] [pid 12345:tid 123456789] [client 192.168.1.100:54321] AH00124: \/var\/www\/html\/index.php pcfg_openfile: unable to check access time of \/var\/www\/html\/index.php\n<\/code><\/pre>\n<p>The <code>AH00124<\/code> error code is the primary indicator of an internal redirect loop. The message might also point to the specific file being repeatedly requested, like <code>index.php<\/code>.<\/p>\n<h3>Root Cause Analysis<\/h3>\n<p>A redirect loop essentially means that a <code>RewriteRule<\/code> in your <code>.htaccess<\/code> file is continuously matching the URL it <em>just<\/em> rewrote, or it&#039;s part of a cycle of two or more rules rewriting back and forth. This leads to an endless internal redirection chain until Apache&#039;s <code>LimitInternalRecursion<\/code> (default 10) is hit, triggering the 500 error.<\/p>\n<p>Common underlying reasons include:<\/p>\n<ol>\n<li><strong>Missing or Incorrect <code>RewriteCond<\/code> (Rewrite Condition):<\/strong> Rules are applied indiscriminately without checking if the target condition (e.g., already HTTPS, already non-WWW) is met. This is the most frequent culprit.<\/li>\n<li><strong>Conflicting <code>RewriteRule<\/code> Directives:<\/strong> Two or more rules that contradict each other, leading to an infinite cycle (e.g., A redirects to B, and B redirects back to A).<\/li>\n<li><strong>Improper Use of Flags (<code>[L]<\/code>, <code>[R]<\/code>, <code>[NC]<\/code>, <code>[OR]<\/code>):<\/strong><ul>\n<li><strong>Lack of <code>[L]<\/code> (Last):<\/strong> Allows Apache to continue processing subsequent rules even after a match, potentially re-matching the same rule or a conflicting one.<\/li>\n<li><strong>Incorrect <code>[R]<\/code> (Redirect):<\/strong> Causes an external HTTP redirect instead of an internal rewrite, which can also loop if not properly conditioned.<\/li>\n<\/ul>\n<\/li>\n<li><strong><code>RewriteBase<\/code> Misconfiguration:<\/strong> In subdirectory installations, an incorrect <code>RewriteBase<\/code> can lead to URI mismatches, causing rules to re-evaluate incorrectly.<\/li>\n<li><strong>Environment Mismatches (e.g., SSL offloading with proxies):<\/strong> When your website is behind a reverse proxy or load balancer that handles SSL, Apache might not see <code>%{HTTPS}<\/code> as <code>on<\/code>. If you then force HTTPS based on <code>%{HTTPS}<\/code>, it will loop.<\/li>\n<li><strong>Caching Issues:<\/strong> Less common for a 500 error, but browser or CDN caches can sometimes store faulty redirects, exacerbating testing.<\/li>\n<li><strong><code>AllowOverride<\/code> Directive:<\/strong> While usually resulting in a 403 Forbidden or rules not being applied, if <code>AllowOverride<\/code> is set to <code>None<\/code> and an old browser cache still tries to apply a redirect, it <em>could<\/em> contribute to confusion. However, for a 500 <code>AH00124<\/code>, the <code>.htaccess<\/code> file <em>is<\/em> being read and processed.<\/li>\n<\/ol>\n<h3>Step-by-Step Resolution<\/h3>\n<p>Follow these steps to diagnose and resolve the Apache <code>.htaccess<\/code> redirect loop.<\/p>\n<h4>1. Backup Your <code>.htaccess<\/code> File<\/h4>\n<blockquote class=\"important\"><p>Before making any changes, always back up your current <code>.htaccess<\/code> file. This allows you to revert to the original state if things go wrong or if you make an incorrect modification.<\/p>\n<\/blockquote>\n<p>You can do this via SSH:<\/p>\n<pre><code class=\"language-bash\">sudo cp \/var\/www\/html\/.htaccess \/var\/www\/html\/.htaccess.backup_$(date +%Y%m%d%H%M%S)\n<\/code><\/pre>\n<h4>2. Locate and Examine Apache Error Logs<\/h4>\n<p>The Apache error logs are your primary source of information. On Debian\/Ubuntu systems, they are typically found here:<\/p>\n<pre><code class=\"language-bash\">sudo tail -f \/var\/log\/apache2\/error.log\n<\/code><\/pre>\n<p>Keep this terminal window open while you attempt to access your website. Look for the <code>AH00124<\/code> error message. It may provide clues about the specific URL or file that&#039;s being repeatedly accessed.<\/p>\n<h4>3. Temporarily Disable <code>mod_rewrite<\/code> or Comment Out Rules<\/h4>\n<p>To quickly confirm if <code>mod_rewrite<\/code> is indeed the cause, you can temporarily disable it or comment out all <code>RewriteRule<\/code> and <code>RewriteCond<\/code> directives.<\/p>\n<ol>\n<li><p><strong>Disable <code>mod_rewrite<\/code> (less recommended for <code>.htaccess<\/code> issues):<\/strong>\nThis requires root access and will affect <em>all<\/em> <code>mod_rewrite<\/code> rules on the server.<\/p>\n<pre><code class=\"language-bash\">sudo a2dismod rewrite\nsudo systemctl restart apache2\n<\/code><\/pre>\n<p>If your site loads (without redirects, potentially looking broken), <code>mod_rewrite<\/code> was the issue. Re-enable with <code>sudo a2enmod rewrite<\/code> after troubleshooting.<\/p>\n<\/li>\n<li><p><strong>Comment out <code>.htaccess<\/code> rules (recommended):<\/strong>\nEdit your <code>.htaccess<\/code> file (e.g., <code>nano \/var\/www\/html\/.htaccess<\/code>) and place a <code>#<\/code> at the beginning of every <code>RewriteRule<\/code> and <code>RewriteCond<\/code> line.<\/p>\n<pre><code class=\"language-apache\">#RewriteEngine On\n#RewriteCond %{HTTPS} off\n#RewriteRule ^(.*)$ https:\/\/%{HTTP_HOST}%{REQUEST_URI} [L,R=301]\n#RewriteCond %{HTTP_HOST} ^www.example.com [NC]\n#RewriteRule ^(.*)$ https:\/\/example.com\/$1 [L,R=301]\n<\/code><\/pre>\n<p>Save the file and try accessing your site. If the 500 error disappears, the issue is definitely within your <code>mod_rewrite<\/code> rules. Re-enable rules one by one or in small groups to pinpoint the problematic one.<\/p>\n<\/li>\n<\/ol>\n<h4>4. Analyze and Correct Common Redirect Loop Scenarios<\/h4>\n<p>Once you&#039;ve identified the problematic rule (or set of rules), apply the following common fixes:<\/p>\n<h5>Scenario A: HTTP to HTTPS Redirect Loop<\/h5>\n<p>This is often caused by the <code>RewriteCond %{HTTPS} off<\/code> not correctly detecting HTTPS when behind a reverse proxy or load balancer.<\/p>\n<p><strong>Problematic Example:<\/strong><\/p>\n<pre><code class=\"language-apache\">RewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https:\/\/%{HTTP_HOST}%{REQUEST_URI} [L,R=301]\n<\/code><\/pre>\n<p>If your server is behind a proxy that terminates SSL, Apache might still see requests as HTTP (<code>%{HTTPS}<\/code> is <code>off<\/code>), even though the user connected via HTTPS. The proxy typically sets an <code>X-Forwarded-Proto<\/code> header.<\/p>\n<p><strong>Solution:<\/strong> Check for <code>X-Forwarded-Proto<\/code> header.<\/p>\n<pre><code class=\"language-apache\"># Correct HTTP to HTTPS redirect, handling proxies\nRewriteEngine On\nRewriteCond %{HTTP:X-Forwarded-Proto} !https [NC]\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https:\/\/%{HTTP_HOST}%{REQUEST_URI} [L,R=301]\n<\/code><\/pre>\n<p>The <code>[NC]<\/code> flag makes the condition case-insensitive. Adding <code>%{HTTPS} off<\/code> as an <code>OR<\/code> condition, or as a fallback, is also a robust approach for environments without proxies.<\/p>\n<h5>Scenario B: WWW to Non-WWW (or vice-versa) Redirect Loop<\/h5>\n<p>Loops can occur when combined with HTTPS redirects, or if the rule isn&#039;t specific enough.<\/p>\n<p><strong>Problematic Example (forcing non-WWW):<\/strong><\/p>\n<pre><code class=\"language-apache\">RewriteEngine On\n# Force non-WWW (might loop with HTTPS or other rules)\nRewriteCond %{HTTP_HOST} ^www.example.com [NC]\nRewriteRule ^(.*)$ http:\/\/example.com\/$1 [L,R=301]\n<\/code><\/pre>\n<p>If you have a separate HTTP to HTTPS rule and then this one, they might conflict, e.g., <code>https:\/\/www.example.com<\/code> -&gt; <code>http:\/\/example.com<\/code> (by this rule) -&gt; <code>https:\/\/example.com<\/code> (by HTTPS rule), leading to a loop.<\/p>\n<p><strong>Solution:<\/strong> Combine redirects and ensure conditions prevent self-matching.<\/p>\n<pre><code class=\"language-apache\"># Combined HTTPS and non-WWW redirect (canonical URL)\nRewriteEngine On\nRewriteCond %{HTTP:X-Forwarded-Proto} !https [NC,OR]\nRewriteCond %{HTTPS} off [OR]\nRewriteCond %{HTTP_HOST} ^www.example.com [NC]\nRewriteRule ^(.*)$ https:\/\/example.com%{REQUEST_URI} [L,R=301]\n<\/code><\/pre>\n<p>This single rule ensures all requests are sent to <code>https:\/\/example.com<\/code>, removing both the <code>www.<\/code> and forcing HTTPS in one go, preventing conflicts. Change <code>example.com<\/code> to your domain.<\/p>\n<h5>Scenario C: Trailing Slash Issues<\/h5>\n<p>Redirecting URLs to add\/remove trailing slashes can loop if not handled carefully, especially with <code>DirectoryIndex<\/code> or file names.<\/p>\n<p><strong>Problematic Example:<\/strong><\/p>\n<pre><code class=\"language-apache\"># Add trailing slash for directories (problem if target is already \/)\nRewriteCond %{REQUEST_FILENAME} -d\nRewriteRule ^(.*[^\/])$ $1\/ [R=301,L]\n<\/code><\/pre>\n<p><strong>Solution:<\/strong> Be specific and use conditions to avoid matching already correct URLs.<\/p>\n<pre><code class=\"language-apache\"># Add trailing slash if a directory AND no slash exists\nRewriteCond %{REQUEST_FILENAME} -d\nRewriteRule ^(.*[^\/])$ \/$1\/ [R=301,L]\n\n# Or, remove trailing slash if not a directory (e.g. for clean URLs)\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteCond %{REQUEST_URI} (.+)\/$\nRewriteRule ^(.*)\/$ $1 [R=301,L]\n<\/code><\/pre>\n<h5>Scenario D: Index File Redirects (e.g., <code>index.php<\/code> removal)<\/h5>\n<p>If you&#039;re rewriting <code>\/index.php<\/code> to <code>\/<\/code>, ensure it doesn&#039;t then try to serve <code>\/index.php<\/code> again implicitly.<\/p>\n<p><strong>Problematic Example:<\/strong><\/p>\n<pre><code class=\"language-apache\">RewriteRule ^(.*)\/index.php$ \/$1\/ [R=301,L]\n<\/code><\/pre>\n<p>If Apache&#039;s <code>DirectoryIndex<\/code> is set to <code>index.php<\/code>, requesting <code>\/<\/code> will internally map to <code>index.php<\/code>, which then matches this rule, leading to a loop.<\/p>\n<p><strong>Solution:<\/strong> Use conditions to avoid matching the base URL after the rewrite, or ensure your <code>DirectoryIndex<\/code> is well-defined.<\/p>\n<pre><code class=\"language-apache\"># Remove index.php from URL, but prevent loop on root\nRewriteCond %{THE_REQUEST} \/index.php [NC]\nRewriteRule ^(.*)index.php$ \/$1 [R=301,L,NC]\n<\/code><\/pre>\n<p><code>%{THE_REQUEST}<\/code> matches the <em>initial<\/em> request line, preventing internal rewrites from triggering the rule again.<\/p>\n<h4>5. Ensure <code>[L]<\/code> (Last) Flag is Used Appropriately<\/h4>\n<p>The <code>[L]<\/code> (Last) flag is crucial. It tells <code>mod_rewrite<\/code> to stop processing the <em>current<\/em> set of rules if the <code>RewriteRule<\/code> matches. Without it, subsequent rules in <code>.htaccess<\/code> might re-evaluate the rewritten URL, potentially leading to a loop. Ensure all final redirect rules (<code>[R=301]<\/code>) also include <code>[L]<\/code>.<\/p>\n<h4>6. Verify <code>AllowOverride<\/code> Directive<\/h4>\n<p>For <code>.htaccess<\/code> files to work, the <code>AllowOverride<\/code> directive in your Apache virtual host configuration or <code>apache2.conf<\/code> must permit it. If <code>AllowOverride<\/code> is set to <code>None<\/code> for the relevant directory, your <code>.htaccess<\/code> rules will be ignored (often resulting in a 403 Forbidden or no redirect at all), but in some edge cases, it can cause unexpected behavior.<\/p>\n<blockquote class=\"important\"><p>The <code>AllowOverride<\/code> directive is configured in your main Apache configuration files, NOT in <code>.htaccess<\/code>. Common locations are <code>\/etc\/apache2\/apache2.conf<\/code> or in your site&#039;s virtual host configuration file (e.g., <code>\/etc\/apache2\/sites-available\/yourdomain.conf<\/code>).<\/p>\n<\/blockquote>\n<p>Open your virtual host configuration file:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/apache2\/sites-available\/yourdomain.conf\n<\/code><\/pre>\n<p>Or the main Apache config:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/apache2\/apache2.conf\n<\/code><\/pre>\n<p>Look for a <code>&lt;Directory&gt;<\/code> block corresponding to your website&#039;s root path (e.g., <code>\/var\/www\/html<\/code>). Ensure <code>AllowOverride<\/code> is set to <code>All<\/code> or <code>FileInfo<\/code>. <code>FileInfo<\/code> is generally sufficient for <code>mod_rewrite<\/code> rules.<\/p>\n<pre><code class=\"language-apache\">&lt;Directory \/var\/www\/yourwebsite&gt;\n    Options Indexes FollowSymLinks\n    AllowOverride All   # Or AllowOverride FileInfo\n    Require all granted\n&lt;\/Directory&gt;\n<\/code><\/pre>\n<p>If you modify your main Apache configuration, you&#039;ll need to restart Apache.<\/p>\n<h4>7. Test Configuration and Restart Apache<\/h4>\n<p>After making any changes to <code>.htaccess<\/code> or main Apache configuration, always test the syntax and restart the server.<\/p>\n<pre><code class=\"language-bash\">sudo apache2ctl configtest\n<\/code><\/pre>\n<p>You should see <code>Syntax OK<\/code>. If not, review the error messages and correct them.<\/p>\n<pre><code class=\"language-bash\">sudo systemctl restart apache2\n<\/code><\/pre>\n<h4>8. Clear Browser Cache<\/h4>\n<blockquote class=\"warning\"><p>Web browsers aggressively cache 301 (Permanent) redirects. If you&#039;ve been testing faulty redirect rules, your browser might have cached the bad redirect, causing it to loop even after you&#039;ve fixed the <code>.htaccess<\/code> file.<\/p>\n<\/blockquote>\n<p>After fixing your <code>.htaccess<\/code> file and restarting Apache, clear your browser&#039;s cache completely, or use an incognito\/private browsing window to test. You can also use <code>curl -I example.com<\/code> from the command line to see HTTP headers and verify redirects without browser caching.<\/p>\n<pre><code class=\"language-bash\">curl -I https:\/\/example.com\ncurl -I http:\/\/www.example.com\n<\/code><\/pre>\n<p>This will show you the exact HTTP response codes (e.g., <code>HTTP\/1.1 301 Moved Permanently<\/code>) and the <code>Location<\/code> header, indicating where the server is attempting to redirect.<\/p>\n<p>By systematically applying these steps, you should be able to identify, correct, and resolve the Apache <code>.htaccess<\/code> redirect loop leading to a 500 Internal Server Error.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fix Apache .htaccess redirect loops causing 500 errors. Learn to troubleshoot mod_rewrite rules, canonical URLs, and SSL configurations to restore site access quickly.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[19,3,14,17,15,6,20],"class_list":["post-8","post","type-post","status-publish","format-standard","hentry","category-web-server","tag-500-error","tag-apache","tag-htaccess","tag-mod_rewrite","tag-redirect-loop","tag-troubleshooting","tag-web-server"],"_links":{"self":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/8","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/comments?post=8"}],"version-history":[{"count":2,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/8\/revisions"}],"predecessor-version":[{"id":256,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/8\/revisions\/256"}],"wp:attachment":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/media?parent=8"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/categories?post=8"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/tags?post=8"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}