vitejs/vite · error · Error

When "build.cssCodeSplit: false" is set, "rolldownOptions.in

Error message

When "build.cssCodeSplit: false" is set, "rolldownOptions.input" should not include CSS files.

What it means

In resolveRolldownOptions (build.ts:633-644), when build.cssCodeSplit is false and any resolved input ends in .css, Vite throws. With code splitting disabled, CSS cannot be treated as a separate entry; CSS must be imported from JS rather than listed directly as an input.

Source

Thrown at packages/vite/src/node/build.ts:641

      ? resolve(options.ssr)
      : options.rolldownOptions.input ||
        (topLevelInput ?? resolve('index.html'))

  if (ssr && typeof input === 'string' && input.endsWith('.html')) {
    throw new Error(
      `rolldownOptions.input should not be an html file when building for SSR. ` +
        `Please specify a dedicated SSR entry.`,
    )
  }
  if (options.cssCodeSplit === false) {
    const inputs =
      typeof input === 'string'
        ? [input]
        : Array.isArray(input)
          ? input
          : Object.values(input)
    if (inputs.some((input) => input.endsWith('.css'))) {
      throw new Error(
        `When "build.cssCodeSplit: false" is set, "rolldownOptions.input" should not include CSS files.`,
      )
    }
  }

  const outDir = resolve(options.outDir)

  // inject environment and ssr arg to plugin load/transform hooks
  const plugins = environment.plugins.map((p) =>
    injectEnvironmentToHooks(environment, chunkMetadataMap, p),
  )

  const rolldownOptions: RolldownOptions = {
    preserveEntrySignatures: ssr
      ? 'allow-extension'
      : libOptions
        ? 'strict'
        : false,

View on GitHub (pinned to 89620f09af)

Solutions

  1. Remove .css files from rolldownOptions.input and import the CSS from a JS/TS entry instead.
  2. If you genuinely need CSS as an entry, leave cssCodeSplit at its default (true).
  3. Move shared styles into a JS entry that does import './styles.css'.

Example fix

// before
build: { cssCodeSplit: false, rollupOptions: { input: { main: 'src/main.ts', styles: 'src/styles.css' } } }
// after
build: { cssCodeSplit: false, rollupOptions: { input: { main: 'src/main.ts' } } } // src/main.ts imports './styles.css'
Defensive patterns

Strategy: validation

Validate before calling

if (config.build?.cssCodeSplit === false) {
  const inputs = config.build?.rolldownOptions?.input
  const list = typeof inputs === 'string' ? [inputs] : Array.isArray(inputs) ? inputs : inputs ? Object.values(inputs) : []
  if (list.some((f) => f.endsWith('.css'))) {
    throw new Error('CSS inputs are not allowed when cssCodeSplit is false')
  }
}

Type guard

function hasNoCssInput(inputs: unknown): boolean {
  const list = typeof inputs === 'string' ? [inputs] : Array.isArray(inputs) ? inputs : inputs ? Object.values(inputs as Record<string, string>) : []
  return !list.some((f: string) => f.endsWith('.css'))
}

Prevention

When it happens

Trigger: Setting build: { cssCodeSplit: false } while rolldownOptions.input (or the default input) includes one or more .css files.

Common situations: Trying to ship a single combined CSS file by disabling code splitting, but also listing the stylesheet as a build entry; copying a multi-entry config that included a CSS entry.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/024c234125b5156b.json. Report an issue: GitHub.