evanw/esbuild · critical
Invalid format
Error message
Invalid format
What it means
validateFormat (pkg/api/api_impl.go:132) panics when Format is not one of FormatDefault(0), FormatIIFE(1), FormatCommonJS(2), FormatESModule(3). Format dictates the output module wrapper; an unknown value means esbuild cannot pick a code generator, so it aborts rather than emit ambiguous output. The panic is reached from validateBuildOptions when constructing OutputFormat.
Solutions
- Use only the documented constants: api.FormatDefault / FormatIIFE / FormatCommonJS / FormatESModule; FormatDefault lets esbuild choose based on Platform and Bundle.
- Sanitize any externally-supplied integer against {0,1,2,3} before casting to Format.
- Lock esbuild to a single version across your stack (go.mod + package.json) and regenerate any bridge code after upgrades.
- Replace numeric `Format` fields in serialized config files with named strings mapped at load time.
Example fix
// before
opts := api.BuildOptions{Format: api.Format(9), Bundle: true}
// after
opts := api.BuildOptions{Format: api.FormatESModule, Bundle: true} Defensive patterns
Strategy: validation
Validate before calling
func checkFormat(f api.Format) error {
switch f {
case api.FormatDefault, api.FormatIIFE, api.FormatCommonJS, api.FormatESModule:
return nil
}
return fmt.Errorf("invalid format %d (want 0..3)", uint8(f))
}
// before build:
if err := checkFormat(opts.Format); err != nil { return err } Type guard
func isValidFormat(f api.Format) bool {
switch f {
case api.FormatDefault, api.FormatIIFE, api.FormatCommonJS, api.FormatESModule:
return true
}
return false
} Prevention
- Use FormatDefault and let esbuild pick (IIFE for browser bundle, CJS for node bundle, ESM for neutral).
- Persist Format as a string ("iife"/"cjs"/"esm") and translate to the constant at load.
- Add a CI check that fails if the vendored esbuild version differs across go.mod and any wrapper.
- Write a config round-trip test exercising every enum field.
When it happens
Trigger: Passing BuildOptions.Format (or TransformOptions.Format) assigned from an integer literal, a deserialized payload, or a stale constant that no longer exists. The panic occurs in the option-validation pass of api.Build/api.Transform/api.Context, before scanning entry points.
Common situations: Bridging the JS API to the Go core with a mismatched version (e.g. js_table.ts regenerated ordinals after a re-vendor), JSON-decoding config where Format is stored as a number, or copying `Format: api.FormatPreserve` (a constant that does not exist in the public API) from outdated docs.
Related errors
AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09).
Data as JSON: /api/errors/edafada400bfbf4b.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/api/api_impl.go:132
case PlatformNeutral:
return config.PlatformNeutral
default:
panic("Invalid platform")
}
}
func validateFormat(value Format) config.Format {
switch value {
case FormatDefault:
return config.FormatPreserve
case FormatIIFE:
return config.FormatIIFE
case FormatCommonJS:
return config.FormatCommonJS
case FormatESModule:
return config.FormatESModule
default:
panic("Invalid format")
}
}
func validateSourceMap(value SourceMap) config.SourceMap {
switch value {
case SourceMapNone:
return config.SourceMapNone
case SourceMapLinked:
return config.SourceMapLinkedWithComment
case SourceMapInline:
return config.SourceMapInline
case SourceMapExternal:
return config.SourceMapExternalWithoutComment
case SourceMapInlineAndExternal:
return config.SourceMapInlineAndExternal
default:
panic("Invalid source map")
}View on GitHub (pinned to f6058f8364)