---
title: "How to return a real 404 with a recoverable body on Lovable"
slug: fix-soft-404-lovable
published: 2026-10-13T13:16:50.19204+00:00
updated: 2026-10-13T13:16:50.19204+00:00
author: "AIScan Content Team"
author_url: https://aiscan.site/about
category: "AI Readiness"
tags: check:E1, platform:lovable, Lovable, 404, soft 404, TanStack Start, AI readiness
description: "Lovable's older React + Vite sites answer missing URLs with 200, while TanStack Start returns 404. Find your stack, fix it, and verify AIScan check E1."
url: https://aiscan.site/blog/fix-soft-404-lovable
---

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:

```text
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:

1. In the project chat, type `/`, choose **Migrate to TanStack Start** and confirm.
2. Or open project settings, go to **General > Project actions** and select **Migrate**.
3. 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`:

```tsx
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:

```tsx
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:**

```bash
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.app` sites 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](https://aiscan.site/guides). Related reading: the [Next.js version of this fix](https://aiscan.site/blog/fix-soft-404-nextjs), [why soft 404s mislead agents](https://aiscan.site/blog/soft-404-agent-discovery-problem), the [Discoverability checks](https://aiscan.site/docs/checks/discoverability) and [AI readiness setup on Lovable](https://aiscan.site/blog/ai-readiness-setup-lovable).

