Next.js

Fix TS2882: side-effect import of './globals.css'

Why this error appears on unchanged Next.js projects overnight, which TypeScript actually raises it, and the one-line ambient declaration that fixes it under both compilers.

Mahdi Ben RhoumaMahdi Ben Rhouma
7 min read

TL;DR#

Up to Next.js 16.1.7, the bundled types declare *.module.css, never a bare .css. For years that was harmless, because typescript@5.9.3 does not type-check a side-effect import — import './globals.css' — unless noUncheckedSideEffectImports is explicitly set to true. A 6.0.0-dev nightly build of TypeScript, and the stable 7.0.2 that followed it, check the same import by default, with no flag required, and raise a dedicated error the 5.x line does not have: TS2882. If your editor is running one of those builds instead of the project's own TypeScript — a VS Code update, or the TypeScript Nightly extension — every plain CSS import in the project starts failing with no code change on your side. Fix it either way with one ambient declaration, with the flag itself (it still works as an override), or by pointing VS Code back at the project's own TypeScript.

text
Cannot find module or type declarations for side-effect import of './globals.css' ts(2882)

Why it happens#

This question (42 votes, over 27,000 views) describes it exactly: the error appears on existing and newly created create-next-app projects, with no manual change to code or dependencies. That detail rules out a project misconfiguration — it points at the tool reading the project, not the project itself.

Reproduced locally on the same two files (app/globals.css + import './globals.css' in app/layout.tsx), switching only the installed typescript package:

  • typescript@5.9.3 with no noUncheckedSideEffectImports key in tsconfig.json: the plain import compiles cleanly, no output, exit code 0. Setting noUncheckedSideEffectImports: true makes the same import fail — but as the generic TS2307, not TS2882:
text
app/layout.tsx(1,8): error TS2307: Cannot find module './globals.css' or its corresponding type declarations.
  • typescript@6.0.0-dev.20250926 — a nightly build dated the same day the Stack Overflow question was asked — fails the identical import with no flag set at all:
text
app/layout.tsx(1,8): error TS2882: Cannot find module or type declarations for side-effect import of './globals.css'.
  • typescript@7.0.2 (npm's current stable typescript, released 2026-07-08) reproduces the same TS2882 with the flag absent. Setting the flag explicitly to false clears it, exit 0 — so the flag still works as an override on this line; only its default changed.

That is the whole mystery: the question's error is a newer compiler's own diagnostic for exactly the thing typescript@5's noUncheckedSideEffectImports flag checks — worded and numbered differently, and switched on by default instead of off.

The practical trigger for "I did not change anything" is almost always the editor, not npm install. VS Code's own TypeScript docs state that the JavaScript and TypeScript Nightly extension "automatically replaces VS Code's built-in TypeScript version with the latest TypeScript nightly build" — and a nightly installable on the asker's own date already produces this exact error with no flag. A VS Code update, or that extension picking up a new nightly, swaps the compiler the editor uses for red squiggles without touching package.json, tsconfig.json or a single source file.

Up to Next.js 16.1.7 (checked back to 15.5.23), the package's own type declarations (next/types/global.d.ts) declare *.module.css, *.module.sass and *.module.scss — never a bare *.css. See the official CSS docs: import './globals.css' is the documented way to load global CSS, and it worked for years precisely because typescript@5.x never looked at it by default. Nothing about that import changed; the compiler reading it did.

Fix#

1. Add one ambient declaration (works on every TypeScript version tested)#

Create (or extend) a .d.ts file included by your tsconfig.json — css.d.ts or global.d.ts at the project root is enough:

typescript
declare module '*.css' {}

Reproduced: with this declaration in place, import './globals.css' compiles cleanly under typescript@7.0.2, with or without noUncheckedSideEffectImports set — npx tsc --noEmit exits 0 and prints nothing, where it printed TS2882 a moment before on the identical layout.tsx. It does not interfere with typed CSS Modules: a *.module.css import still resolves through the more specific *.module.css pattern — assigning its typed export to an incompatible type (const n: number = styles) still raised TS2322: Type '{ readonly [key: string]: string; }' is not assignable to type 'number', proving the two declarations coexist without one swallowing the other.

2. Or let Next.js 16.2.0+ provide it for you#

From Next.js 16.2.0 onward, next/types/global.d.ts ships this exact pair, added specifically for this case:

typescript
// These are needed for `noUncheckedSideEffectImports` support
// See: https://www.typescriptlang.org/tsconfig/#noUncheckedSideEffectImports
declare module '*.css' {}
declare module '*.sass' {}
declare module '*.scss' {}

Confirmed by reading the published package directly: next@16.1.7's global.d.ts has no bare *.css declaration; next@16.2.0's does, and next@16.2.0's package entry (index.d.ts) references that file by triple-slash, so it loads automatically through the next-env.d.ts every create-next-app project already has — no manual .d.ts needed. A project pinned to 16.1.x or earlier (checked back to 15.5.23) needs option 1 or 3 instead.

3. Set the flag explicitly to false#

If your editor is the one running a 6.x/7.x-line TypeScript, noUncheckedSideEffectImports: false in tsconfig.json still clears the error — reproduced: the same import that failed with the key absent compiled cleanly once the key was set to false. This is the flag SO answer 3 names; on typescript@5.x it is a no-op (the check is already off by default there), so it is safe to set on either compiler line.

4. If it is only VS Code that is wrong, not your build#

If next build or a terminal tsc --noEmit passes but VS Code still underlines the import, the editor is using a different TypeScript than your project's node_modules. Open any .ts/.tsx file, run TypeScript: Select TypeScript Version from the command palette, and pick Use Workspace Version. If you have the JavaScript and TypeScript Nightly extension installed and don't need it, disable it — it is the extension that swaps VS Code onto the nightly builds in the first place.

Verify the fix#

bash
npx tsc --noEmit

A clean exit (no TS2882 or TS2307 on the CSS import, no output at all on ./globals.css) confirms the fix independently of the editor and of whichever TypeScript VS Code happens to be running. If you used option 1, double-check a CSS Modules import elsewhere in the project still type-checks its class names against the real shape Next.js generates for them — the reproduction above shows the *.module.css pattern keeps winning over the broader *.css one, but it is still worth a glance at one real file in your own codebase before moving on.

One email a month — the latest explained errors

What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.

Variants#

  • import './globals.scss' or .sass behaves identically to the plain .css case reproduced above — add declare module '*.scss' {} / '*.sass' {} alongside the .css one, or upgrade to Next.js 16.2.0+, whose global.d.ts already declares all three extensions side by side.
  • Tailwind's single @import 'tailwindcss' entry point (see the CSS docs) hits the same error the same way: the file is still a .css file loaded as a side-effect import in app/layout.tsx, so the same ambient declaration fixes it regardless of what rules the file itself contains.
  • If the error instead reads Global CSS cannot be imported from files other than your Custom <App>, that is a different, Pages-Router-specific restriction enforced by Next.js at build time, not by TypeScript's type checker — see Fix Next.js Global CSS cannot be imported: Pages Router for that one; it has its own fix (move the import into pages/_app) that this article's ambient declaration does not touch.

This is a compiler-version problem hiding behind a project-looking error: the fastest check, before touching any config, is comparing npx tsc -v in a terminal against whatever VS Code reports in its status bar for the active file — if they disagree, you have found the cause before reading a single line of your own code. Once the import itself compiles, two more Next.js + TypeScript pages cover what else can turn up next, and they are not the same severity: Fix Export encountered errors on following paths in Next.js is for an actual build-time failure — it reads the path list next build prints back to the real exception a few lines above it. Failed to find font override values: next/font/google fix is different: it covers a next/font console warning that appears for a similar reason — a value Next.js's own bundled data does not have for your font — but, per that page's own TL;DR, it does not break the build; it is a non-blocking warning, not a build error.

Frequently Asked Questions

|

Have more questions? Contact us

Still stuck? Paste your error.

Paste the error message or stack trace — we check it against every fix and tool on the site.

Matching happens in your browser. When you search, a cleaned error signature is sent so we can spot errors we do not cover yet — never the raw text, your IP address or your e-mail. Do not paste passwords or keys. Details

Written by

Mahdi Ben Rhouma
Mahdi Ben Rhouma

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote