evanw/esbuild · error · Error

must be

Error message

${quote(key)} must be ${mustBe}

What it means

Every esbuild option is type-checked by getFlag() at lib/shared/common.ts:77 against a `mustBe` predicate (mustBeBoolean, mustBeString, mustBeInteger, etc.). When an option key is present but its value fails the predicate, esbuild throws naming the key and the expected type. This catches silent misbehavior from loosely-typed config before it reaches the binary.

Solutions

  1. Coerce the value to the exact type the option expects (string->Boolean for flags, string->Number for integers, etc.) before calling esbuild.
  2. Check the option's expected type in the esbuild docs and fix the source producing the wrong type.
  3. Adopt esbuild's TypeScript types (BuildOptions/TransformOptions) so the editor flags the mismatch at authoring time.

Example fix

// before (bundle as string from env)
await build({ entryPoints: ['app.ts'], bundle: process.env.BUNDLE })

// after
await build({ entryPoints: ['app.ts'], bundle: process.env.BUNDLE === 'true' })
Defensive patterns

Strategy: type-guard

Type guard

// Narrow each option to its expected type before calling esbuild.
function asBoolean(v, fallback) {
  if (v === undefined) return fallback
  if (typeof v === 'boolean') return v
  if (v === 'true') return true
  if (v === 'false') return false
  throw new TypeError(`expected boolean, got ${typeof v}: ${v}`)
}
// e.g. bundle: asBoolean(opts.bundle, false)

Prevention

When it happens

Trigger: Passing e.g. `bundle: 'true'` (string not boolean), `target: 2020` (number not string/array), `logLimit: '10'` (string not integer), `mangleProps: '/^_/'` (string not RegExp), or `sourcemap: 'yes'` where a boolean is required to build()/context()/transform().

Common situations: Loading options from JSON/env files where all values are strings; YAML parsing producing strings for unquoted tokens; passing numeric IDs where strings are expected; coercion gaps when forwarding user input.

Related errors


AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09). Data as JSON: /api/errors/a31bb478a51c58a6. Report an issue: GitHub.

Appendix: source

Thrown at lib/shared/common.ts:82

  typeof value === 'string' || typeof value === 'object' && value !== null && !Array.isArray(value) ? null : 'a string or an object'

let mustBeStringOrArrayOfStrings = (value: string | string[] | undefined): string | null =>
  typeof value === 'string' || (Array.isArray(value) && value.every(x => typeof x === 'string')) ? null : 'a string or an array of strings'

let mustBeStringOrUint8Array = (value: string | Uint8Array | undefined): string | null =>
  typeof value === 'string' || value instanceof Uint8Array ? null : 'a string or a Uint8Array'

let mustBeStringOrURL = (value: string | URL | undefined): string | null =>
  typeof value === 'string' || value instanceof URL ? null : 'a string or a URL'

type OptionKeys = { [key: string]: boolean }

function getFlag<T, K extends (keyof T & string)>(object: T, keys: OptionKeys, key: K, mustBeFn: (value: T[K]) => string | null): T[K] | undefined {
  let value = object[key]
  keys[key + ''] = true
  if (value === undefined) return undefined
  let mustBe = mustBeFn(value)
  if (mustBe !== null) throw new Error(`${quote(key)} must be ${mustBe}`)
  return value
}

function checkForInvalidFlags(object: Object, keys: OptionKeys, where: string): void {
  for (let key in object) {
    if (!(key in keys)) {
      throw new Error(`Invalid option ${where}: ${quote(key)}`)
    }
  }
}

export function validateInitializeOptions(options: types.InitializeOptions): types.InitializeOptions {
  let keys: OptionKeys = Object.create(null)
  let wasmURL = getFlag(options, keys, 'wasmURL', mustBeStringOrURL)
  let wasmModule = getFlag(options, keys, 'wasmModule', mustBeWebAssemblyModule)
  let worker = getFlag(options, keys, 'worker', mustBeBoolean)
  checkForInvalidFlags(options, keys, 'in initialize() call')
  return {

View on GitHub (pinned to f6058f8364)