evanw/esbuild · critical
Invalid target
Error message
Invalid target
What it means
A panic raised by validateFeatures when the Target value is not one of the documented ECMA targets (ES5, ES2015..ES2025, ESNext, DefaultTarget). Reachable only through Go-API misuse that constructs an out-of-range Target; the JS API's Target union ('es5' | 'es2015' | ... | 'esnext') maps to valid constants and cannot trigger it.
Source
Thrown at pkg/api/api_impl.go:335
case ES2018:
constraints[compat.ES] = compat.Semver{Parts: []int{2018}}
case ES2019:
constraints[compat.ES] = compat.Semver{Parts: []int{2019}}
case ES2020:
constraints[compat.ES] = compat.Semver{Parts: []int{2020}}
case ES2021:
constraints[compat.ES] = compat.Semver{Parts: []int{2021}}
case ES2022:
constraints[compat.ES] = compat.Semver{Parts: []int{2022}}
case ES2023:
constraints[compat.ES] = compat.Semver{Parts: []int{2023}}
case ES2024:
constraints[compat.ES] = compat.Semver{Parts: []int{2024}}
case ES2025:
constraints[compat.ES] = compat.Semver{Parts: []int{2025}}
case ESNext, DefaultTarget:
default:
panic("Invalid target")
}
for _, engine := range engines {
if match := versionRegex.FindStringSubmatch(engine.Version); match != nil {
if major, err := strconv.Atoi(match[1]); err == nil {
parts := []int{major}
if minor, err := strconv.Atoi(match[2]); err == nil {
parts = append(parts, minor)
if patch, err := strconv.Atoi(match[3]); err == nil {
parts = append(parts, patch)
}
}
constraints[convertEngineName(engine.Name)] = compat.Semver{
Parts: parts,
PreRelease: match[4],
}
continue
}View on GitHub (pinned to 6ff1d8b0d8)
Solutions
- Use only the documented Target constants (ES5, ES2015..ES2025, ESNext, DefaultTarget).
- For a future/unknown target, fall back to ESNext rather than casting a number.
- Validate deserialized target values against an allowlist.
- Pin a single esbuild version and re-check target support after upgrades.
Example fix
// before opts.Target = api.Target(123) // after opts.Target = api.ES2022 // or ESNext for bleeding-edge
Defensive patterns
Strategy: type-guard
Validate before calling
func validTarget(t api.Target) bool {
switch t {
case api.DefaultTarget, api.ES5, api.ES2015, api.ES2016, api.ES2017, api.ES2018, api.ES2019, api.ES2020, api.ES2021, api.ES2022, api.ES2023, api.ES2024, api.ES2025, api.ESNext:
return true
}
return false
} Type guard
type Target = 'es5' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'es2023' | 'es2024' | 'es2025' | 'esnext'
const TARGETS = new Set<Target>(['es5','es2015','es2016','es2017','es2018','es2019','es2020','es2021','es2022','es2023','es2024','es2025','esnext'])
function isTarget(v: unknown): v is Target {
return typeof v === 'string' && (TARGETS as Set<string>).has(v)
} Prevention
- Use only documented Target constants.
- For bleeding-edge output use ESNext, never a guessed ordinal.
- Re-check supported targets after each esbuild upgrade.
When it happens
Trigger: Go API: BuildOptions.Target = Target(123). The JS API cannot reach this panic. Fires inside validateFeatures during the target/engine compatibility computation.
Common situations: Reflective config decoding; fork ordinal drift; unsafe casts; passing a numeric target from a roadmap string like 'es2030' that esbuild does not yet know.
Related errors
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/c7304a3391daf108.json.
Report an issue: GitHub.