Skip to content
Latchkey

Vite SSR "Cannot read properties of undefined" - Externalize Deps

In an SSR build, Vite externalizes most dependencies (leaves them as runtime require/import) by default. When a dependency must be transformed by Vite to work under SSR - or one that should stay external is bundled - the server build throws at import or render time.

What this error means

A Vite SSR build or vite-node/framework SSR run fails with an import-time crash (Cannot read properties of undefined, default is not a function, require is not defined) tied to one dependency. It works in the client build but not on the server.

vite ssr output
TypeError: Cannot read properties of undefined (reading 'createElement')
    at Module.render (/app/node_modules/some-ui-lib/dist/index.cjs.js)
    at renderToString (/app/dist/server/entry-server.js)
[vite] Error when evaluating SSR module

Diagnose it: is it resolution, transform, or memory?

Bundler failures in CI fall into three families and the error text often points at the wrong one. A module that resolves on your machine and not on the runner is nearly always case sensitivity or a missing optional dependency; a transform error is a config or version mismatch; and an unexplained kill with no stack is the out-of-memory reaper, not a build error at all.

Terminal
# 1. resolution: does the file exist with EXACTLY that case?
git ls-files | grep -i "the/imported/path"

# 2. transform: what versions is CI actually resolving?
npm ls webpack vite rollup esbuild typescript 2>/dev/null | head -20

# 3. memory: was it killed rather than failed?
#    exit 137 = SIGKILL (OOM). Nothing in the bundler log will explain it.
node --max-old-space-size=4096 node_modules/.bin/vite build

Common causes

A dep needs Vite transform under SSR

Some packages (CSS-in-JS, libraries shipping ESM-only or needing interop) break when externalized for SSR. They must be added to ssr.noExternal so Vite bundles and transforms them for the server.

A native/runtime-only dep was bundled

Conversely, a package with native bindings or that reads __dirname/files at load can break when Vite tries to bundle it for SSR; it must be kept external.

How to fix it

Control externalization explicitly

Use ssr.noExternal to bundle a dep, or ssr.external to keep one external.

vite.config.ts
// vite.config.ts
export default defineConfig({
  ssr: {
    noExternal: ['some-ui-lib'],   // bundle + transform for SSR
    external: ['better-sqlite3'],  // keep native dep external
  },
})

Diagnose which side the dep belongs on

  1. If the error is missing interop / ESM evaluation, add the dep to ssr.noExternal.
  2. If it is a native binding or filesystem-at-load package, add it to ssr.external.
  3. Reproduce with the SSR build in CI, not just the client build.

Make the build reproducible before you debug it

  • Pin the Node major in setup-node and in engines. A bundler that resolves native bindings will pick a different prebuilt binary across majors.
  • Delete node_modules locally and reinstall from the lockfile before concluding the runner is at fault; most "works locally" reports are stale local state.
  • Set CI=true locally to reproduce. Several toolchains change behaviour under it, including treating warnings as errors.
  • Exit code 137 is an out-of-memory kill. Raise --max-old-space-size or move to a larger runner rather than searching the bundler config.

How to prevent it

  • List SSR-incompatible deps in ssr.noExternal deliberately.
  • Keep native/runtime-only deps in ssr.external.
  • Run the SSR build in CI so externalization bugs fail before deploy.

Frequently asked questions

What causes Vite SSR "Cannot read properties of undefined"?
There are 2 common causes: a dep needs vite transform under ssr and a native/runtime-only dep was bundled. Some packages (CSS-in-JS, libraries shipping ESM-only or needing interop) break when externalized for SSR.
How do I fix Vite SSR "Cannot read properties of undefined"?
There are 2 fixes depending on which cause you have: control externalization explicitly and diagnose which side the dep belongs on. Work through them in order, since the first is the most common.
What does Vite SSR "Cannot read properties of undefined" actually mean?
A Vite SSR build or vite-node/framework SSR run fails with an import-time crash (Cannot read properties of undefined, default is not a function, require is not defined) tied to one dependency.
How do I stop Vite SSR "Cannot read properties of undefined" happening again?
List SSR-incompatible deps in ssr.noExternal deliberately. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card