localhost:5173 / blank-page

localhost:5173 loads but the page stays blank

A blank page on localhost:5173 is a dev-server problem only if the document request itself fails — a 404 with an empty body means Vite found no index.html in the project root — while a 200 with an empty page means a script failed in the browser, which Vite does not show in the terminal by default.

error
# DevTools → Network, first row
GET http://localhost:5173/ 404 (Not Found)
# response body: empty

Which request do I look at first?

The document request — the first row in the Network tab, the one for / itself. Its status code splits the problem in two before anything else. A 404, 403 or 500 there means the dev server did not hand over a working page. A 200 means the server did its job, and the blank page is what your JavaScript made of it.

  • 404, empty response body — no index.html where Vite looks for it.
  • 404 with a sentence about a "public base URL" — the base option, not a missing file.
  • 403 with "403 Restricted" — a file outside server.fs.allow.
  • 500 and a red overlay — a transform error, also printed in the terminal.
  • 200 — the server is fine. Open the Console tab.

A 404 with an empty body means there is no index.html in the root

With the default appType of "spa", every HTML request that does not match a file is rewritten to /index.html. If that file does not exist in the project root either, the HTML middleware passes, and the last middleware in the chain answers with status 404 and no body at all. The browser renders that as a white tab — no error text, nothing in the terminal. The root is process.cwd() unless root is set, so running vite from a parent folder, or keeping index.html under src/, produces exactly this.

vite source — middlewares/notFound.ts (v8.3.0)
return function vite404Middleware(_, res) {
  res.statusCode = 404
  res.end()   // no body — the tab stays white
}

With appType "custom", Vite serves no HTML at all

SSR setups and frameworks with their own HTML handling set appType to "custom". Vite then does not register its HTML fallback, index.html handling or 404 middleware — whatever sits in front of Vite has to answer the document request. If the server that should do that is not running, or does not match the route, nothing answers with a page.

Why is there an error overlay for some errors and not others?

The overlay only appears when the server sends an error. That happens when a file fails to transform — a syntax error, a failed import resolution, a plugin throwing. The dev server then logs the error in the terminal, pushes it to the browser as an overlay and answers the module request with 500. An exception thrown while your code runs in the browser never reaches the server, so there is no overlay, no terminal line, and the page simply stays empty.

vite source — client/client.ts (v8.3.0)
case 'error': {
  ...
  if (enableOverlay) {
    createErrorOverlay(err)   // only for errors sent by the server
  }
}

Fixing a compile error on first load triggers a full reload

When the page opens with a transform error already present, the module graph never finishes loading — the source comment says the whole module script failed because one nested import returned 500. A normal hot update cannot repair that, so the first update after the fix reloads the page instead. If the page stays blank after that reload, the compile error was not the only problem.

Getting browser errors into the terminal

server.forwardConsole sends uncaught exceptions, unhandled promise rejections and selected console calls from the browser to the Vite terminal. Its default is auto: on only when Vite detects an AI coding agent, off otherwise — so in a normal terminal session a runtime error that blanks the page shows up in the browser console and nowhere else. Turning it on is the quickest way to see the error where the dev server output already is.

vite.config.js
export default {
  server: {
    forwardConsole: {
      unhandledErrors: true,
      logLevels: ['warn', 'error']
    }
  }
}

A base path looks like a blank page from the wrong URL

With base set to something like "/app/", a visit to / or /index.html is redirected to the base with a 302, so the root still works. Any other path outside the base gets a 404 whose body is a single sentence pointing at the right URL. Opened from a bookmark or an old link, that one line is all there is — no app, no styles — and it is easy to read as an empty page.

browser
GET http://localhost:5173/dashboard
404 The server is configured with a public base URL of /app/ -
    did you mean to visit /app/dashboard instead?

A 403 means a file outside the serving allow list

server.fs.strict is on by default. When a requested file resolves to a path outside the allowed directories — common in monorepos and with linked packages — the dev server answers 403 and serves a short "403 Restricted" page instead of the file. The terminal names the file and lists the current allow entries.

terminal
The request id "/repo/packages/ui/dist/index.js" is outside of Vite serving allow list.

- /repo/apps/web
Refer to docs https://vite.dev/config/server-options.html#server-fs-allow

# faq

Questions

Why does localhost:5173 show a white page with no error?

Either the document request returned 404 with an empty body, because there is no index.html in the project root, or the page loaded with 200 and a script failed in the browser. The status code of the first request in the Network tab tells you which.

Where does Vite look for index.html?

In the project root, which is process.cwd() unless the root option says otherwise. Running vite from the wrong folder is enough to get a blank 404.

Why is there no error overlay for my blank page?

The overlay only shows errors the server sends, such as a failed transform. Exceptions thrown while your code runs in the browser do not reach the server and appear only in the browser console.

Can Vite show browser errors in the terminal?

Yes, with server.forwardConsole. Its default is auto, which is only on when an AI coding agent is detected, so in a normal session you have to enable it.

Is a blank page a Vite bug?

Rarely. If the first request returns 200, the dev server delivered the page and the cause is in the application code or its dependencies.

The page is blank only on some routes. Why?

With a base option set, paths outside the base return a 404 with a one-line hint instead of the app. Check whether the URL starts with the configured base.

# next

Related