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
- Coerce the value to the exact type the option expects (string->Boolean for flags, string->Number for integers, etc.) before calling esbuild.
- Check the option's expected type in the esbuild docs and fix the source producing the wrong type.
- 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
- Use esbuild's exported BuildOptions/TransformOptions TypeScript types for your config object.
- When reading options from env/JSON, coerce to the documented type before forwarding.
- Write a small zod/joi schema for config loaded from untrusted sources.
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
- Expected value for supported
- Expected value for to be a string, got instead
- Invalid option
- Expected in mangle cache to map to either a string or false
- Invalid banner file type
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)