Table of contents
Lovable can return a real 404 or a soft 200 for the same missing URL, and which one you get depends on the stack your project was built on. AIScan check E1 (Correct 404 handling) grades both the status code and the page body, so a 200 on /zz-nope fails it outright. I probed live Lovable sites on 13 October 2026: a project on the newer TanStack Start template answered 404, and two older React + Vite projects answered 200 for a path that does not exist. This guide shows how to tell which you have and how to fix each.
Quick summary
| Your Lovable stack | Unknown URL returns | Fix |
|---|---|---|
| TanStack Start (default for new projects since 13 May 2026) | 404 with your page | Make sure that page has links (Step 3) |
| Older React + Vite | 200, the same empty app shell | Migrate to TanStack Start (Step 2) |
| React + Vite, cannot migrate yet | 200 | Add noindex to the not-found view (Step 4) |
Fastest route: run npx aiscan-cli yoursite.com and read E1, Correct 404 handling. The by-hand check is in Step 5.
What Lovable serves for a missing page
I requested a made-up path and a made-up .md path on three published lovable.app sites, each with curl under a browser user agent:
| Site stack | /zz-nope-123 | /zz-nope-123.md |
|---|---|---|
| React + Vite (two sites) | 200, ~3.3 to 3.7 KB, <div id="root"></div>, 0 links | 404, text/plain, 9 bytes |
| TanStack Start (one site) | 404, text/html, ~12.9 KB, rendered "Page not found" | 404 |
The Vite sites show why this is a soft 404. The server has no idea which routes exist, so it sends the same index.html for every path and lets React Router decide in the browser. The page a visitor sees says "Oops! Page not found", but the response already went out as 200. Note the .md row: the platform answers that one itself, so a probe with only a .md path would wrongly tell you the site is fine.
Lovable's own docs draw the same line. New apps created from 13 May 2026 use server-side rendering; older apps serve pre-rendered copies only to verified search and AI crawlers, and other tools see the plain single-page app.
Step 1: Find out which stack you are on
Ask the project chat:
What stack is this project on?
Lovable's upgrade documentation suggests this exact question. Or open the live site, choose View source and look at the body: an empty <div id="root"></div> means React + Vite.
Step 2: Migrate a Vite project to TanStack Start
This is the real fix, because only a server can set a status code. Lovable's documentation gives three ways in:
- In the project chat, type
/, choose Migrate to TanStack Start and confirm. - Or open project settings, go to General > Project actions and select Migrate.
- Or ask Lovable in plain words to upgrade the app to TanStack Start.
Lovable states that most upgrades cost 10 to 35 credits, that the live site keeps serving the old version until you publish again, and that you can revert from version history. Test your pages in the preview, then click Publish.
If Migrate to TanStack Start is missing, the project is probably on TanStack Start already.
Step 3: Give the 404 page links and cover missing records
On TanStack Start the router throws a not-found error for any URL that matches no route, and the status code follows. What is left is the body. On the TanStack site I probed, the 404 page had exactly one link, to /. Check E1 wants a page an agent can recover from, so list your main sections.
TanStack Router's documentation lets you set one component for the whole app through defaultNotFoundComponent:
const router = createRouter({
defaultNotFoundComponent: () => (
<div>
<h1>Page not found</h1>
<p><a href="/">Home</a> · <a href="/pricing">Pricing</a> · <a href="/blog">Blog</a> · <a href="/sitemap.xml">Sitemap</a></p>
</div>
),
})
Replace the links with your own. If you cannot find createRouter, ask Lovable to add a not-found page with those links.
Dynamic routes need one more rule. The documentation says that for a record that does not exist, such as /posts/missing-slug, you must throw notFound() in the route's loader. That is the call that turns a missing record into a not-found response instead of an empty page.
Step 4: If you must stay on React + Vite
A static host cannot send a 404 for a client-side route. Google's JavaScript SEO guide names two options for single-page apps. The redirect to a /not-found URL that returns 404 does not work here, because every path on these sites returns 200. That leaves the other one: add <meta name="robots" content="noindex"> when the route is missing. In your catch-all not-found component:
useEffect(() => {
const meta = document.createElement("meta");
meta.name = "robots";
meta.content = "noindex";
document.head.appendChild(meta);
return () => meta.remove();
}, []);
This keeps Googlebot from indexing the empty page. It does not change the status code, so E1 will still report a failure. Migrating is the only complete fix.
Step 5: Verify the fix
With AIScan (default): run npx aiscan-cli yoursite.com and find E1, Correct 404 handling under Discoverability. After the fix it should pass.
By hand with curl:
curl -s -o /dev/null -w '%{http_code}\n' https://yoursite.com/this-page-does-not-exist-9f3a
curl -s https://yoursite.com/this-page-does-not-exist-9f3a | grep -a -c '<a '
Expected: 404, then a link count of at least 2. A 200 means you are still on the Vite stack, or the migration is not published yet. Test your custom domain too, not only the lovable.app address.
Edge cases
- Redirects to a custom domain. Several
lovable.appsites I tried answer with a 302 to their own domain, so probe the domain visitors use. - Browser-only libraries. Lovable warns that some libraries can break server rendering after the upgrade. Open every page in the preview before publishing.
- Sign-in pages. Lovable says it inventories protected pages first and carries the protection over, but check one logged-out visit to a private URL.
Next step
Run the scan on your domain and read the rest of the series in AIScan's guides. Related reading: the Next.js version of this fix, why soft 404s mislead agents, the Discoverability checks and AI readiness setup on Lovable.
Frequently asked questions
Why does my Lovable site return 200 for a page that does not exist?
Your project is probably on the older React + Vite stack. The host sends the same index.html for every path, and React Router shows the not-found view in the browser, after the 200 has gone out. TanStack Start renders on the server and can return 404.
How do I know whether my Lovable project uses TanStack Start?
Ask the project chat "What stack is this project on?". Or view the page source of the live site: an empty <div id="root"></div> means React + Vite. Lovable made TanStack Start the default for new projects on 13 May 2026.
The Migrate to TanStack Start option is missing. What do I do?
Your project is probably already on TanStack Start, or Lovable cannot determine its stack. Ask the chat which stack the project uses. If it says TanStack Start, skip the migration and check the 404 page body instead.
AIScan E1 still fails after I migrated. Why?
Check that you published after the migration, then request a made-up URL on your custom domain. If the status is 404 but E1 fails, the page body has no links. Add links to your main sections in the not-found component.
My made-up .md URL returns 404, but my normal missing URL returns 200. Is that a problem?
Yes. The platform answers the .md path itself, so it hides the soft 404. Always probe a plain path such as /this-page-does-not-exist-9f3a, as the curl check in this guide does.
Does a noindex meta tag fix the soft 404 on React + Vite?
Partly. It tells Google not to index the empty page, which is one of two strategies in Google's JavaScript SEO guide for single-page apps. The status code stays 200, so AIScan E1 still fails until you migrate.
Will migrating to TanStack Start change how my app looks?
Lovable says no: it carries your design, theme and content across, and the live site keeps the old version until you publish. You can revert the upgrade from version history if the result is wrong.
What does the Lovable migration cost?
Lovable's documentation says most upgrades cost 10 to 35 credits, depending on project size. Anyone with edit permission on the project can start one, on all plans.
Related guides
What a Failing AIScan Check Really Says: 2,961 Fail Lines Audited
A failing check on a scan report is supposed to be an instruction. The site owner reads the line, knows what the scanner asked for, knows what came back, and knows what to change. We audited whether…
How to return a real 404 with a recoverable body on Wix
Wix gets the status code right and leaves the page empty. Request a URL that does not exist on a Wix site and you get a genuine 404, but the body is a scriptbuilt shell with no text and no links in…
Which Agent-Readiness Checks Travel Together: 739 Sites, Three Bundles
Fix one agentreadiness check and a second one often moves with it. Fix another and nothing else changes. A scan report lists every check as its own line, so the reader cannot see which lines are…
How to return a real 404 with a recoverable body on Docusaurus
Docusaurus builds a real 404.html for you, and then the place you test it hides it. Run npm start, type a madeup URL and you get a friendly page with a 200 status. The production build behaves…
