nextjs - 💡(How to fix) Fix Turbopack CSS optimizer strips @media keyword when nesting rules [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#91624Fetched 2026-04-08 00:57:48
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Error Message

Error: Parsing CSS source code failed — Invalid empty selector

Root Cause

The @vanilla-extract/turbopack-plugin is at v0.1.1 — this may also be partially a vanilla-extract integration issue, but the root cause is Turbopack's CSS processing stripping the @media keyword during rule nesting optimization. The CSS is valid when it enters Turbopack's pipeline.

Code Example

import { style } from '@vanilla-extract/css';

export const stickyNav = style({
  position: 'sticky',
  left: 0,
  zIndex: 2,
  '@media': {
    '(min-width: 1024px)': {
      position: 'relative'
    }
  }
});

---

.stickyNav__abc123 {
  position: sticky;
  left: 0;
  z-index: 2;
  (min-width: 1024px) {
    position: relative;
  }
}

---

/* Flat (as generated by vanilla-extract): */
.stickyNav__abc123 { position: sticky; left: 0; z-index: 2; }
@media (min-width: 1024px) { .stickyNav__abc123 { position: relative; } }

/* Or valid nested CSS: */
.stickyNav__abc123 {
  position: sticky;
  left: 0;
  z-index: 2;
  @media (min-width: 1024px) {
    position: relative;
  }
}

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin 25.3.0
Binaries:
  Node: 22.x
  pnpm: 10.32.1
Relevant Packages:
  next: 16.1.7
  react: 19.2.4
  @vanilla-extract/css: 1.19.1
  @vanilla-extract/next-plugin: 2.5.1
  @vanilla-extract/turbopack-plugin: 0.1.1
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

Reproduction steps below (no sandbox needed — reproducible with any vanilla-extract project using @media in style() calls).

To Reproduce

  1. Create a Next.js 16.1.7 project with Turbopack enabled
  2. Install @vanilla-extract/[email protected] with unstable_turbopack: { mode: 'auto' }
  3. Create a .css.ts file with @media inside style():
import { style } from '@vanilla-extract/css';

export const stickyNav = style({
  position: 'sticky',
  left: 0,
  zIndex: 2,
  '@media': {
    '(min-width: 1024px)': {
      position: 'relative'
    }
  }
});
  1. Start the dev server with next dev --turbopack

Current vs. Expected behavior

Current behavior: Turbopack's CSS optimizer nests the flat @media rule into the selector block and strips the @media keyword, producing invalid CSS:

.stickyNav__abc123 {
  position: sticky;
  left: 0;
  z-index: 2;
  (min-width: 1024px) {
    position: relative;
  }
}

Error: Parsing CSS source code failed — Invalid empty selector

Expected behavior: The CSS should remain as valid flat CSS or valid nested CSS:

/* Flat (as generated by vanilla-extract): */
.stickyNav__abc123 { position: sticky; left: 0; z-index: 2; }
@media (min-width: 1024px) { .stickyNav__abc123 { position: relative; } }

/* Or valid nested CSS: */
.stickyNav__abc123 {
  position: sticky;
  left: 0;
  z-index: 2;
  @media (min-width: 1024px) {
    position: relative;
  }
}

Debugging performed

We confirmed via logging in the @vanilla-extract/turbopack-plugin loader that the CSS returned by the loader is correct — it contains proper @media (min-width: ...) blocks at the top level. The corruption happens after the loader returns the CSS, during Turbopack's internal CSS processing.

Things we tested that did NOT fix the issue:

  • unstable_splitCssPerRule: true vs false — no difference
  • Removing screen and from media queries — no difference
  • Removing all PostCSS plugins (empty config) — no difference
  • Removing browserslist from package.json — no difference

This confirms the bug is in Turbopack's own CSS optimizer (SWC CSS), not in PostCSS, vanilla-extract, or user code.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin 25.3.0
Binaries:
  Node: 22.x
  pnpm: 10.32.1
Relevant Packages:
  next: 16.1.7
  react: 19.2.4
  @vanilla-extract/css: 1.19.1
  @vanilla-extract/next-plugin: 2.5.1
  @vanilla-extract/turbopack-plugin: 0.1.1

Which area(s) are affected?

Turbopack

Which stage(s) are affected?

next dev (Turbopack)

Additional context

The @vanilla-extract/turbopack-plugin is at v0.1.1 — this may also be partially a vanilla-extract integration issue, but the root cause is Turbopack's CSS processing stripping the @media keyword during rule nesting optimization. The CSS is valid when it enters Turbopack's pipeline.

extent analysis

Fix Plan

To fix the issue with Turbopack's CSS optimizer stripping the @media keyword, we need to update the @vanilla-extract/turbopack-plugin to handle media queries correctly.

Here are the steps:

  • Update @vanilla-extract/turbopack-plugin to the latest version.
  • If the issue persists, try disabling the CSS optimizer in Turbopack by setting unstable_cssOptimization: false in your next.config.js file:
module.exports = {
  //... other configurations ...
  experimental: {
    turbopack: {
      unstable_cssOptimization: false,
    },
  },
}

Alternatively, you can try using a custom CSS processor in your next.config.js file:

module.exports = {
  //... other configurations ...
  experimental: {
    turbopack: {
      css: {
        processor: 'css-modules',
      },
    },
  },
}

If none of the above solutions work, you may need to wait for an update to the @vanilla-extract/turbopack-plugin or Turbopack itself that fixes the issue.

Verification

To verify that the fix worked, start your development server with next dev --turbopack and check the generated CSS for the presence of the @media keyword. The CSS should be valid and contain the @media keyword.

Extra Tips

  • Make sure to keep your dependencies up to date, as newer versions may include fixes for known issues.
  • If you're using a custom PostCSS configuration, try removing it to see if it's causing the issue.
  • You can also try using a different CSS processor, such as postcss, to see if it resolves the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING