How AI-Generated .htaccess Rules Can Break WordPress
AI tools can generate WordPress code fast, .htaccess rules included. That speed is useful, but .htaccess is one of the riskiest places to paste AI-generated code without review. A single rewrite rule changes how requests reach WordPress, and it can touch the homepage, the login page, admin AJAX, the REST API, WooCommerce checkout, forms, redirects and static files.
The real danger is that the site still looks like it works. The homepage loads and the menu opens, while checkout, search, a form or a payment fails silently, because the request is intercepted before WordPress ever sees it.
This article explains why AI-generated .htaccess rules break WordPress, the mistakes to avoid, and how to review a rule before it goes live. For the wider picture, see our post on common mistakes with AI-generated code in WordPress.
What is .htaccess in WordPress?
.htaccess is Apache’s per-directory configuration file. Its rules apply to the folder it sits in and every folder below it, and Apache reads it again on every request. LiteSpeed, which some hosts run instead of Apache, is built to understand Apache’s configuration and follows its rewrite syntax. Nginx has no .htaccess at all. WordPress uses the file for pretty permalinks with this block:
# 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
Requests for files and folders that exist are served as they are (the !-f and !-d checks); everything else goes to index.php, and WordPress decides what to show. The dash in the index.php line means “no substitution”: requests for that file pass straight through and skip the file checks.
Two things follow. When WordPress writes its rules, which saving Settings > Permalinks does, it replaces everything between # BEGIN WordPress and # END WordPress and keeps the rest of the file, so your own rules go above or below the block, never inside it. And anything above the block runs first, before WordPress gets a say. That is where the trouble starts.
Why AI-generated .htaccess code is risky
AI can produce a rule that looks technically valid:
RewriteRule ^$ /home.html [L]
It reads as “send homepage requests to home.html“. But WordPress also handles dynamic requests on the homepage address with a query string. WooCommerce’s classic checkout, for instance, refreshes the order totals with:
/?wc-ajax=update_order_review
A rule meant for the homepage catches that request too, and WooCommerce receives a static HTML page instead of the JSON it expected. The customer sees checkout loading forever, an order review that never updates, missing payment methods or a Place order button that does nothing.
This is not hypothetical. In one WooCommerce case we traced, exactly this pattern made checkout load forever while the rest of the site looked healthy. The rule looks small. The impact can be large.
Mistake 1: Using static HTML rewrites inside a dynamic WordPress site
A typical AI suggestion for a faster homepage is a static file plus a rule like this:
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^$ /home.html [L]
The condition adds nothing: REQUEST_URI is the path without the query string, so /?wc-ajax=update_order_review passes it like any homepage visit. The result is a mixed architecture, with the homepage served as static HTML and everything else by WordPress, while plugins, forms and WooCommerce expect normal routing. That mix is fragile.
Let WordPress serve the homepage: a page chosen under Settings > Reading or a front-page.php template, with page caching for speed. Our guide to converting static HTML into a WordPress theme shows how to keep an AI-generated design without the rewrite.
Mistake 2: Forgetting that query strings matter
A RewriteRule pattern is matched against the path only, never the query string, and in .htaccess the leading slash is removed first. So to ^$, all of these are the site root:
/?wc-ajax=update_order_review
/?rest_route=/wp/v2/posts
/?s=search-term
/?add-to-cart=123
Those are WooCommerce’s checkout requests, the REST API on sites without pretty permalinks, the WordPress search form and WooCommerce’s add-to-cart links. Apache even passes the original query string on to the new target by default, and a static file simply ignores it.
If you really must keep a static homepage, limit the rule to plain page views: GET or HEAD requests with no query string, from visitors who are not logged in and have nothing in their cart.
RewriteCond %{REQUEST_METHOD} ^(GET|HEAD)$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{HTTP_COOKIE} !(wordpress_logged_in_|woocommerce_items_in_cart) [NC]
RewriteRule ^$ /home.html [L]
Conditions combine with AND, so the rule only fires when all three match. Even so, the better answer is usually no rewrite at all: a theme template keeps WordPress in charge, and a page cache set up the way WooCommerce’s caching guide describes handles these exceptions for you.
Mistake 3: Placing custom rules before WordPress without knowing the impact
Rules near the top of the file see the request before WordPress does:
RewriteEngine On
RewriteRule ^$ /home.html [L]
# BEGIN WordPress
...
# END WordPress
[L] is often explained as “last rule”, which is only half true in .htaccess. It ends the current pass, but Apache then runs the rewritten request through the file again, so a rule whose result matches its own pattern can loop until Apache gives up after ten internal redirects (LimitInternalRecursion). [END] stops rewriting for good. On LiteSpeed, [L] already acts like Apache’s [END], one reason a rule can behave differently on two hosts.
Habits from the main server configuration fail quietly too: Apache’s documentation says a pattern starting with ^/ never matches in per-directory context, so RewriteRule ^/old-page$ /new-page/ [R=301,L] does nothing in .htaccess. Before placing anything above the WordPress block, ask whether it could affect AJAX, the REST API, checkout, login and account pages, query strings, multilingual URLs or caching.
Mistake 4: Redirecting cart, checkout or account pages
AI-generated rules that clean up URLs, force trailing slashes or redirect old pages can collide with the pages, endpoints and query-string requests WooCommerce relies on:
/cart/
/checkout/
/checkout/order-received/
/my-account/
/my-account/lost-password/
/?wc-ajax=...
/?wc-api=...
Those are the default English slugs; a store set up in another language gets translated ones. Rules like these are risky:
RewriteRule ^checkout$ /checkout/ [R=301,L]
RewriteRule ^my-account$ /login/ [R=301,L]
- Redirect loops. WordPress already redirects visitors to its canonical address, with or without www, for example. A server rule pointing the other way bounces the browser back and forth until it gives up.
- Lost form data. On a 301 or 302 a browser may turn a POST into a GET, so a redirect in front of a form, checkout or callback can drop what was sent. WordPress itself never redirects POST requests to canonical URLs.
- Lost query strings. A substitution ending in
?, or the[QSD]flag, throws the query string away. That breakswc-ajaxrequests and payment callbacks such as PayPal Standard’s, which WooCommerce’s gateway documentation shows as the homepage address plus?wc-api=. - Endpoints sent nowhere. Apache’s
Redirectkeeps the rest of the path, soRedirect 301 /my-account /loginalso sends/my-account/lost-password/to/login/lost-password/, which does not exist.
Leave cart, checkout and account pages alone unless there is a specific reason, and test the full order flow, payment included, afterwards.
Mistake 5: Returning HTML where AJAX expects JSON
A WooCommerce AJAX request expects JSON such as {"result":"success","fragments":{}}. A bad rule returns <!DOCTYPE html> and a whole page instead. The browser may still show 200 OK, but checkout’s JavaScript cannot use the answer. Open the Network panel, filter on Fetch/XHR and inspect the failing request’s URL, status, headers, content type and body: wc-ajax=update_order_review for the classic checkout, requests under /wp-json/wc/store/ for the Checkout block. WooCommerce’s troubleshooting guide lists what turns its JSON into HTML: a cache, maintenance or security layer, a redirect, a proxy or a PHP warning. Our post on WooCommerce checkout stuck loading goes through each cause.
Mistake 6: Using .htaccess for problems WordPress should handle
Many AI-generated rules solve at server level what WordPress handles more safely, and Apache’s own documentation calls mod_rewrite a last resort when simpler tools exist.
- Homepage: instead of
RewriteRule ^$ /home.html [L], set a static homepage under Settings > Reading or buildfront-page.php. - Redirects: instead of
RewriteRule ^old-page$ /new-page [R=301,L], use a redirect plugin for anything editors maintain. For a few fixed redirects, Apache recommends its simplerRedirectandRedirectMatchoverRewriteRule. - Assets: instead of
RewriteRule ^assets/(.*)$ /custom-folder/$1 [L], load files withwp_enqueue_style()andwp_enqueue_script(). - Checkout changes: instead of
RewriteRule ^checkout/(.*)$ /custom-checkout.php [L], use WooCommerce’s hooks and template overrides.
Mistake 7: Pasting caching and header blocks that hit every page
Ask an AI tool to speed up WordPress and you may get something like this:
<IfModule mod_headers.c>
Header set Cache-Control "public, max-age=31536000"
</IfModule>
Unscoped, that header goes on every successful response Apache sends, including the pages WordPress builds through index.php: cart, checkout and My account too. WooCommerce sends no-cache headers on exactly those pages. Header set replaces a header of the same name, and where PHP runs on PHP-FPM through mod_proxy_fcgi, Apache’s documentation warns it can leave both values in the response instead. Either way, checkout now carries a one-year cache header. Scope the rule to static files:
<FilesMatch "\.(css|js|png|jpe?g|gif|webp|avif|svg|woff2?)$">
Header set Cache-Control "public, max-age=31536000"
</FilesMatch>
A long lifetime is only safe when a file’s URL changes whenever the file does, which is what the version WordPress adds to enqueued files is for. Notice the <IfModule> wrapper, too. Apache only reads what is inside it when the module is loaded, and its documentation says normal configurations do not need it. If mod_headers is missing, the wrapped rule silently does nothing, while the same rule unwrapped gives a 500 error. Check in the browser that the header is really there.
Mistake 8: Not testing logged-in and logged-out visitors
Rules can test cookies, the request method and the query string, and WooCommerce asks caches to skip visitors who carry its cart and session cookies. A logged-in admin may see the right pages while customers get cached or redirected ones. After a change, test logged in and logged out, in a private window, on a phone, through the whole product-to-checkout flow, plus a form, search, login, the account page and any REST API or AJAX endpoints you rely on.
Mistake 9: Not keeping a backup, and not reading the 500
One broken line in .htaccess can take the whole site down with a 500 internal server error. The usual causes:
- A typo. Apache’s error log names it, for example
RewriteCond: bad flag delimiters. - A directive the host does not allow.
AllowOverridein the server configuration decides what.htaccessmay contain, and anything else is a server error. A line such asOptions -IndexesneedsAllowOverride Options. - A module that is not loaded. An unknown directive is an error too. Apache’s own test for whether
.htaccessis read at all is to type a nonsense word into it and look for the 500. - PHP settings in the wrong place.
php_valueandphp_flaglines, for example to raise memory or upload limits, belong to PHP running as an Apache module and are unknown directives without it. Where PHP runs as FastCGI or PHP-FPM, use a.user.inifile.
Before changing the file, download a copy or save one outside the public web root. Make one change at a time and reload the site after each. If it breaks, put the backup back immediately.
Mistake 10: Ignoring cache and CDN layers
After you fix .htaccess, the old behaviour can seem to continue because a cache plugin, a server cache, the CDN or the browser still holds old responses. Clear the relevant caches and retest. Redirects need extra care: a 301 is cacheable by default, so a wrong permanent redirect can keep firing from visitors’ browsers after you remove the rule. Test new redirects as 302, which is what Apache’s [R] flag sends when you give no code, and switch to 301 once they are right.
For WooCommerce, keep cart, checkout and My account out of page and edge caching, and make sure the cache, CDN and firewall let WooCommerce’s AJAX requests through:
/cart/
/checkout/
/my-account/
/?wc-ajax=
How to review an AI-generated .htaccess rule safely
- What exact request should it affect? “The homepage” is a weak answer. Better: only a GET request to
/with no query string, from a visitor who is not logged in, never AJAX, REST API or WooCommerce. - Does it handle or ignore query strings? The pattern never sees them.
- Could it touch WordPress’s dynamic routes? Check
/wp-admin/,/wp-login.php,/wp-json/,/?wc-ajax=,/?wc-api=, cart, checkout and My account. - Is there a WordPress-native solution? If yes, prefer it.
- Can you test it on staging, on the same kind of server as the live site?
- Is there a rollback plan? Keep the backup within reach.
Quick debug checklist: did .htaccess break WordPress?
- Do the site and
/wp-admin/load? Do permalinks and/wp-json/work? - Is the homepage served by WordPress or by a static file?
- Does the checkout’s AJAX request return JSON? Does checkout complete?
- Any redirect loops? Do CSS and JS load? Do search and the contact form work?
- Did you clear the caches, and does restoring the previous
.htaccessfix it?
Restoring the previous version and retesting is often the fastest way to confirm that .htaccess is responsible.
When to ask for help
Bring in a specialist when checkout loads forever, WooCommerce AJAX returns HTML, redirects behave inconsistently, the admin works but the front end fails, the site broke right after an AI-generated change, or nobody can say what a rule does. The cause may be one line, but finding it means following the request path properly.
Reviewing and fixing AI-written .htaccess rules is part of our WordPress fixing service: free diagnosis, a fixed price in writing before we start (from €199), and if we can’t fix it, you pay nothing. If the change surfaced PHP errors, PHP bug fixing works on the same terms. Send us the issue; we reply within 30 minutes during business hours and follow the request to the real cause before changing anything.
Final thoughts
AI can generate .htaccess rules quickly, but that does not make them safe for WordPress. The risk comes from adding server-level rules without knowing what WordPress, WooCommerce and plugins expect from each request. Before using one, ask: what else could this rule affect? That question can save hours of debugging and lost orders.
Sources
Last checked 12 November 2026.
- Apache HTTP Server Tutorial: .htaccess files. Per-directory scope, read on every request, AllowOverride, server errors for disallowed directives, the nonsense-word test and the error log examples.
- Apache: mod_rewrite. The pattern never sees the query string, no leading slash in .htaccess, ^/ never matching there, the query string passed on, REQUEST_URI, HTTP_COOKIE, REQUEST_METHOD, the dash and the -f and -d checks.
- Apache: RewriteRule Flags. [L] in per-directory context, [END], [R] defaulting to 302, and [QSD].
- Apache: When not to use mod_rewrite. A last resort; Redirect and RedirectMatch for simple redirects, and Redirect keeping the rest of the path.
- Apache: mod_headers and core. Header set, duplicates with mod_proxy_fcgi, IfModule, FilesMatch and LimitInternalRecursion.
- LiteSpeed: rewrite rules and Apache to LiteSpeed Web Server Migration FAQ. Apache-compatible configuration and rewrites, and [L] acting like Apache’s [END].
- WordPress: Apache HTTPD / .htaccess and Nginx. The WordPress block, and no .htaccess on Nginx.
- WordPress: Settings Permalinks screen, insert_with_markers() and WP_Rewrite::mod_rewrite_rules(). Saving permalinks writes the file, only the marked block is replaced, and the block’s IfModule wrapper and index.php shortcut.
- WordPress REST API Handbook: Routes and Endpoints, get_search_form(), redirect_canonical() and Cookies. ?rest_route=, search on ?s=, canonical redirects that skip POST, and the wordpress_logged_in_ cookie.
- WordPress Theme Handbook: Template Hierarchy and Including Assets. front-page.php, enqueueing, and the version used for cache busting.
- WooCommerce: Endless loading/spinner on the checkout page. Classic and block checkout requests, what turns JSON into HTML, and the layers that must let WooCommerce AJAX through.
- WooCommerce on GitHub: class-wc-ajax.php, class-wc-cache-helper.php and class-wc-install.php. wc-ajax on the homepage address, no-cache headers on cart, checkout and My account, and translated page slugs.
- WooCommerce developer docs: How to configure caching plugins for WooCommerce and Understanding WooCommerce endpoints. Pages and cookies kept out of the cache, and the endpoints.
- WooCommerce: Creating WooCommerce add-to-cart URLs, WooCommerce Payment Gateway API and Template structure and overriding templates via a theme. ?add-to-cart=, PayPal Standard’s ?wc-api= callback, and template overrides.
- IETF RFC 9110: HTTP Semantics, 301 and 302. A browser may turn POST into GET, and a 301 is cacheable by default.
- PHP Manual: How to change configuration settings and .user.ini files. php_value for PHP as an Apache module, and .user.ini for CGI and FastCGI.
Related articles
How to Convert Static HTML into a WordPress Theme Without Breaking the Site
AI can generate a good-looking static HTML site in minutes, but forcing it into WordPress with file uploads and .htaccess rewrites breaks routing, plugins, forms and checkout. This 18-step guide shows how to convert static HTML into a proper WordPress theme, with header, footer, enqueued assets, menus and native WooCommerce intact.
Read articleBefore You Paste AI-Generated PHP into WordPress, Check These Things
AI can write a WordPress PHP snippet in seconds, but pasted in without review it can trigger warnings, break checkout AJAX, cause a white screen, or create redirect loops. Here are the 14 things to check before you paste AI-generated PHP into WordPress, from variable checks and sanitization to hooks, nonces, and a safer placement strategy, with before-and-after code.
Read articleAI-Generated WordPress Code Review Checklist
AI can generate WordPress code in seconds, but a snippet that looks correct can still break checkout, redirects, AJAX, or plugin compatibility. This 20-point checklist gives you a practical way to review AI-generated code before it touches functions.php, .htaccess, or WooCommerce, covering placement, hooks, sanitization, escaping, security, performance, and a rollback plan.
Read article