evanw/esbuild · critical

Invalid engine name

Error message

Invalid engine name

What it means

convertEngineName (pkg/api/api_js_table.go:48) panics when an EngineName passed in BuildOptions.Engines[i].Name is not one of the 11 declared iota constants (EngineChrome, EngineDeno, EngineEdge, EngineFirefox, EngineHermes, EngineIE, EngineIOS, EngineNode, EngineOpera, EngineRhino, EngineSafari). The file is auto-generated by js_table.ts; the panic indicates the public enum and the generated switch are out of sync, or a caller injected an Engine with a numeric Name from outside the declared set.

Source

Thrown at pkg/api/api_js_table.go:48

		return compat.Edge
	case EngineFirefox:
		return compat.Firefox
	case EngineHermes:
		return compat.Hermes
	case EngineIE:
		return compat.IE
	case EngineIOS:
		return compat.IOS
	case EngineNode:
		return compat.Node
	case EngineOpera:
		return compat.Opera
	case EngineRhino:
		return compat.Rhino
	case EngineSafari:
		return compat.Safari
	default:
		panic("Invalid engine name")
	}
}

View on GitHub (pinned to f6058f8364)

Solutions

  1. Construct Engine values using only the declared api.Engine* constants (Chrome, Deno, Edge, Firefox, Hermes, IE, IOS, Node, Opera, Rhino, Safari).
  2. Bounds-check any externally supplied integer against 0..10 before casting to EngineName.
  3. Map engine names from strings at the application boundary and reject unknown ones explicitly.
  4. After adding/removing an engine, regenerate pkg/api/api_js_table.go from js_table.ts and rebuild everything that links the Go core.

Example fix

// before
engines := []api.Engine{{Name: api.EngineName(20), Version: "100"}}
opts := api.BuildOptions{Engines: engines}

// after
engines := []api.Engine{{Name: api.EngineNode, Version: "20"}}
opts := api.BuildOptions{Engines: engines}
Defensive patterns

Strategy: validation

Validate before calling

func checkEngineName(n api.EngineName) error {
    switch n {
    case api.EngineChrome, api.EngineDeno, api.EngineEdge, api.EngineFirefox,
        api.EngineHermes, api.EngineIE, api.EngineIOS, api.EngineNode,
        api.EngineOpera, api.EngineRhino, api.EngineSafari:
        return nil
    }
    return fmt.Errorf("invalid engine name %d (want 0..10)", uint8(n))
}

for i, e := range opts.Engines {
    if err := checkEngineName(e.Name); err != nil { return fmt.Errorf("engines[%d]: %w", i, err) }
}

Type guard

func isValidEngineName(n api.EngineName) bool {
    switch n {
    case api.EngineChrome, api.EngineDeno, api.EngineEdge, api.EngineFirefox,
        api.EngineHermes, api.EngineIE, api.EngineIOS, api.EngineNode,
        api.EngineOpera, api.EngineRhino, api.EngineSafari:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Constructing an Engine literal with `Name: api.EngineName(N)` for N outside 0..10, deserializing Engines from JSON where Name is a number, or running a generated bridge whose js_table.ts predates a renumbering/addition of an engine constant. Reached via validateFeatures when iterating Engines.

Common situations: Code generators or cgo bindings that hand-build Engine structs, version skew between the auto-generated table and a hand-edited wrapper, or attempting to add a new engine by writing an integer instead of extending the enum and regenerating the table.

Related errors


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