Vite Manifest Not Found in Laravel (npm run build)

The problem: After deploying or running npm run build, Laravel throws a Vite manifest exception and every page using @vite() in Blade breaks with a 500 error.

Environment: Laravel 11.x, laravel-vite-plugin ^1.0, Vite 5.x, Node 20 LTS, deployed on Ubuntu 22.04 (also reproducible locally on Windows/WSL2).

The Error

▲ resources/views/layouts/app.blade.php
Illuminate\Foundation\ViteException
Unable to locate file in Vite manifest: resources/css/app.css.

  at vendor/laravel/framework/src/Illuminate/Foundation/Vite.php:410
  406▕     protected function manifestHash(string $buildDirectory): ?string
  407▕     {
  408▕         ...
  409▕     }
 410▕     throw new ViteException("Unable to locate file in Vite manifest: {$path}.");
  411▕
  412▕     public function asset(string $asset, ?string $buildDirectory = null): string

Why It Happens

Laravel's @vite() directive doesn't read your source files directly in production — it reads public/build/manifest.json, a file that Vite generates when you run npm run build. That manifest maps each entry point (like resources/css/app.css) to its hashed, compiled filename (like app-4f9a2e1c.css).

This exception fires in one of three situations, and it's almost never actually a "Laravel" bug:

  1. You never ran npm run build on this environment, so public/build/ doesn't exist at all.
  2. You built the assets, but public/build was excluded by .gitignore, a deploy script, or a Docker .dockerignore, so it never made it to the server.
  3. The path you're asking for in Blade (resources/css/app.css) doesn't match, character-for-character, an entry point listed in vite.config.js.

Since the manifest is a static snapshot, any mismatch between what Blade requests and what Vite actually built throws this exact exception — Laravel has no fallback because in production it deliberately won't compile on the fly.

The Fix

Step 1 — Confirm the manifest actually exists on the server:

ls -la public/build/manifest.json

If that file doesn't exist, run the build on that environment:

$ npm install
$ npm run build

Step 2 — Match your Blade calls to your actual Vite entry points. Open vite.config.js and check the input array:

laravel({
    input: ['resources/css/app.css', 'resources/js/app.js'],
    refresh: true,
}),

Then make sure your Blade layout calls @vite() with the exact same paths, in the exact same casing:

@vite(['resources/css/app.css', 'resources/js/app.js'])

Step 3 — If the manifest exists but deploy still fails, check your .gitignore and deploy pipeline. public/build is ignored by default in a fresh Laravel install, which is correct for git, but your CI/CD step must run npm run build as part of the deploy — it can't just git pull and expect compiled assets to appear.

Step-by-Step

  1. SSH into the environment throwing the error and run ls public/build/manifest.json to confirm it's missing.
  2. Run npm install && npm run build locally or in your CI step, never by hand-editing files on the server.
  3. Open vite.config.js and copy the exact strings from the input array.
  4. Paste those exact strings into your @vite([...]) call in the Blade layout — don't retype them.
  5. Check your deploy script (GitHub Actions, Forge, Envoyer, custom bash) and confirm a build step runs after the code is pulled and before the app goes live.
  6. Clear Laravel's view cache after deploying, since a cached compiled Blade view can hold a stale reference: php artisan view:clear.
⚠ Edge case: if you're using npm run dev locally and everything works, but production fails, check that APP_ENV isn't stuck on local in your production .env. When APP_ENV=local, Vite tries to connect to the dev server on localhost:5173 instead of reading the manifest — and if that dev server isn't running on your production box (it shouldn't be), you'll get connection errors that look similar to a manifest issue but have a completely different root cause.

Still stuck after checking all three causes above? Reach out on the Contact page and send me your vite.config.js — I'll take a look.

Advertisement
Advertisement