vercel / vercel/next.js

styledComponents: css prop hoisting causes "Cannot access 'X' before initialization"

Open
#98,359 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CSS SWC Turbopack Webpack
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/BrianMwit/next-styled-component-issue-repro

To Reproduce

Run npm run dev and loading http://localhost:3000
or Run npm run build, it fails during "Collecting page data"

Also reproducible with --webpack if the page is changed to Client Component by uncommenting https://github.com/BrianMwit/next-styled-component-issue-repro/blob/main/app/page.tsx#L2

Current vs. Expected behavior

Current: the page fail to render
npm run build fail to pre-render the page with the following log:

  Collecting page data using 5 workers  ..Error: Failed to collect configuration for /
    at ignore-listed frames {
  [cause]: ReferenceError: Cannot access 'bn' before initialization
      at module evaluation (app/page.tsx:9:30)
      at module evaluation (app/page.tsx:10:1)
     7 |
     8 | export default function Home() {
  >  9 |   return <Box css={`color: ${COLOR}`}>Red color text</Box>
       |                              ^
    10 | }
    11 |
}

npm run dev fail the same way, both on server-side and browser-side

⨯ ReferenceError: Cannot access 'COLOR' before initialization
    at Module.eval (app/page.tsx:9:30)
    at module evaluation (.next/dev/server/chunks/ssr/[root-of-the-server]__1ewui8sb5lzwz._.js:69:47)
   7 |
   8 | export default function Home() {
>  9 |   return <Box css={`color: ${COLOR}`}>Red color text</Box>
     |                              ^
  10 | }
  11 | {
  page: '/'
}
 GET / 500 in 17ms (next.js: 13ms, application-code: 4ms)
[browser] Uncaught ReferenceError: Cannot access 'COLOR' before initialization
    at Module.eval (app/page.tsx:9:30)
    at module evaluation (app/page.tsx:10:1)
    at Array.map (<anonymous>)
   7 |
   8 | export default function Home() {
>  9 |   return <Box css={`color: ${COLOR}`}>Red color text</Box>
     |                              ^
  10 | }
  11 |

Expected: In https://github.com/BrianMwit/next-styled-component-issue-repro/blob/main/app/page.tsx#L6, move const COLOR = 'red' above const Box and the application runs with red color style applied

Provide environment information
Operating System:
  Platform: linux (Ubuntu 24.04)
  Arch: arm64
  Version: #139-Ubuntu SMP PREEMPT_DYNAMIC Sat Aug  1 03:32:48 UTC 2026
  Available memory (MB): 12502
  Available CPU cores: 14
Binaries:
  Node: 24.20.0
  npm: 11.19.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 16.4.0-canary.20 // Latest available version is detected (16.4.0-canary.20).
  eslint-config-next: N/A
  react: 19.2.8
  react-dom: 19.2.8
  typescript: 5.9.3
Next.js Config:
  output: N/A

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.6.0: Fri Jul 31 19:17:26 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 14
Binaries:
  Node: 24.19.0
  npm: 11.17.0
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 16.4.0-canary.20 // Latest available version is detected (16.4.0-canary.20).
  eslint-config-next: N/A
  react: 19.2.8
  react-dom: 19.2.8
  typescript: 5.9.3
Next.js Config:
  output: N/A
Which area(s) are affected? (Select all that apply)

CSS, SWC, Turbopack, Webpack

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local)

Additional context

styledComponents transform hoists the css prop into a styled(...) template like this

var d = styled(({children}) => jsx("div", {children}))
    .withConfig({displayName: "page___StyledBox", componentId: "sc-efa2cfa0-0"})`color: ${e}`; // try to read `e` here
let e = "red";   // COLOR (`e`) declared here
a.s(["default", 0, function () {
    return (0, b.jsx)(d, { children: "Red color text" }); // COLOR (`e`) was meant to be read here
}]);

COLOR (or e) originally got read on line 9, where Box is instantiated. It now gets read on Box declaration (line 5) instead, causing the error.

This looks like the same issue as https://github.com/styled-components/babel-plugin-styled-components/issues/426. The swc port of that plugin seems to inherit the same defect.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction and app/page.tsx, especially the Box declaration and COLOR constant, then inspect the styledComponents transform in the SWC path. Run npm run dev and npm run build to reproduce the initialization error, including the --webpack client-component case. Done means the example renders and builds with COLOR declared below Box, while preserving the css prop styling.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nextjs, react, typescript, webpack
Domain
build-system, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.