Short answer
Find the file in the stack trace. If it is inside node_modules, that package is browser-only: import it only on the client (a dynamic import with ssr: false inside a Client Component in Next.js, or inside useEffect), or look for a server or Node.js build of it. If it is your own library, build it with output.globalObject set to 'this' or use globalThis. If it is your own code, replace self with globalThis.
Where self comes from, and the fix
01
A browser-only package imported on the server
Chart, map, editor and analytics libraries often reference self as soon as they are imported. In Next.js, load them on the client only, from a Client Component, because ssr: false is not allowed in Server Components.
'use client'; import dynamic from 'next/dynamic'; const Chart = dynamic(() => import('./Chart'), { ssr: false });02
Your own library built with webpack
“To make UMD build available on both browsers and Node.js, set output.globalObject option to 'this'.” webpack, Output: output.globalObject
For web-like targets, webpack’s UMD wrapper is called with self as the global object, so it throws when the bundle is loaded in Node.js. Set the global object so the bundle works in both.
// webpack.config.js module.exports = { output: { library: { name: 'myLib', type: 'umd' }, globalObject: 'this', }, };03
Your own code uses self
“The globalThis property provides a standard way of accessing the global this value (and hence the global object itself) across environments.” MDN, globalThis
self, window and global each exist only in some runtimes. globalThis exists in all of them.
const root = globalThis;04
Tests running in Node.js
A test that imports a browser package fails the same way under the default Node.js test environment. Use a jsdom environment for that test, or mock the package.
Checked against the vendor’s docs on : webpack: output.globalObject; MDN: globalThis.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: Next.js “window is not defined” · “document is not defined” · webpack “Module parse failed”