vitejs/vite · error · Error

Either "build.lib.entry" or the top-level "input" option is

Error message

Either "build.lib.entry" or the top-level "input" option is required when "build.lib" is set.

What it means

In resolveRolldownOptions (build.ts:605), when build.lib is set but build.lib.entry is null/undefined, Vite has no entry point to bundle for the library and throws. The message notes that either build.lib.entry or the top-level input option must supply the entry.

Source

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

    false,
    patchConfig,
    patchPlugins,
  )
}

export function resolveRolldownOptions(
  environment: Environment,
  chunkMetadataMap: ChunkMetadataMap,
): RolldownOptions {
  const { root, packageCache, base, build: options } = environment.config
  const libOptions = options.lib
  const { logger } = environment
  const ssr = environment.config.consumer === 'server'

  const resolve = (p: string) => path.resolve(root, p)
  const topLevelInput = environment.config.input
  if (libOptions && libOptions.entry == null) {
    throw new Error(
      `Either "build.lib.entry" or the top-level "input" option is required when "build.lib" is set.`,
    )
  }
  const input = libOptions
    ? options.rolldownOptions.input ||
      (typeof libOptions.entry === 'string'
        ? resolve(libOptions.entry)
        : Array.isArray(libOptions.entry)
          ? libOptions.entry.map(resolve)
          : Object.fromEntries(
              Object.entries(libOptions.entry!).map(([alias, file]) => [
                alias,
                resolve(file),
              ]),
            ))
    : typeof options.ssr === 'string'
      ? resolve(options.ssr)
      : options.rolldownOptions.input ||

View on GitHub (pinned to 89620f09af)

Solutions

  1. Add build.lib.entry pointing to your entry file, e.g. entry: 'src/index.ts'.
  2. Alternatively provide a top-level input option that the library build can fall back to.
  3. Double-check the entry path is correct and resolvable from root.

Example fix

// before
build: { lib: { name: 'myLib', formats: ['es', 'umd'] } }
// after
build: { lib: { entry: 'src/index.ts', name: 'myLib', formats: ['es', 'umd'] } }
Defensive patterns

Strategy: validation

Validate before calling

if (config.build?.lib && config.build.lib.entry == null && config.input == null) {
  throw new Error('build.lib.entry (or top-level input) is required for library mode')
}

Type guard

function hasLibEntry(config: UserConfig): boolean {
  return !config.build?.lib ||
    config.build.lib.entry != null ||
    config.input != null
}

Prevention

When it happens

Trigger: Configuring build: { lib: { name: 'myLib', formats: ['es'] } } without an entry field, and not providing a top-level input option either.

Common situations: Setting up library mode and forgetting the entry, or renaming the entry field; migrating a config where entry was previously inferred from input.

Related errors


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