evanw/esbuild · critical

Invalid platform

Error message

Invalid platform

What it means

esbuild panics in validatePlatform (pkg/api/api_impl.go:117) when BuildOptions.Platform holds a Platform value outside the declared iota enum. Platform is a `uint8` whose only valid values are PlatformDefault(0), PlatformBrowser(1), PlatformNode(2), PlatformNeutral(3); the function switch has no default case, so any other value aborts the process. The panic exists because the public Go API assumes callers pass declared constants, so an out-of-range value signals corruption the bundler cannot safely continue past.

Solutions

  1. Assign Platform only via the declared constants: api.PlatformDefault / PlatformBrowser / PlatformNode / PlatformNeutral, or leave the field unset to use the zero-value PlatformDefault.
  2. If deserializing options from JSON/protobuf, validate the integer is in {0,1,2,3} before casting to Platform, or use a string mapping table you control.
  3. Rebuild/realign the binary and any bridge/generator against the same esbuild commit so enum ordinals match.
  4. Pin the esbuild version in go.mod / package.json so a future re-vendor cannot silently renumber the iota.

Example fix

// before
opts := api.BuildOptions{Platform: api.Platform(7)}
res := api.Build(opts)

// after
opts := api.BuildOptions{Platform: api.PlatformBrowser}
res := api.Build(opts)
Defensive patterns

Strategy: validation

Validate before calling

// validPlatform maps the only acceptable numeric values for api.Platform.
var validPlatform = map[api.Platform]bool{
    api.PlatformDefault: true,
    api.PlatformBrowser: true,
    api.PlatformNode:   true,
    api.PlatformNeutral:true,
}

func checkPlatform(p api.Platform) error {
    if !validPlatform[p] {
        return fmt.Errorf("invalid platform %d (want 0..3)", uint8(p))
    }
    return nil
}

// call before api.Build / api.Context / api.Transform:
if err := checkPlatform(opts.Platform); err != nil { return err }

Type guard

func isValidPlatform(p api.Platform) bool {
    switch p {
    case api.PlatformDefault, api.PlatformBrowser, api.PlatformNode, api.PlatformNeutral:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Calling api.Build / api.Context / api.Transform with a BuildOptions struct whose Platform field was assigned from a raw integer (e.g. `Platform: 99`), produced by JSON unmarshalling into a `uint8` cast to Platform, or constructed by a code generator / FFI bridge whose numeric mapping differs from this esbuild version. The panic fires synchronously inside validateBuildOptions -> validatePlatform before any file is read.

Common situations: Mixing esbuild versions (host Go binary built from one checkout, JS/CLI bridge expecting another), hand-rolling a BuildOptions over a serialization boundary, copying example code from a newer docs page against an older binary, or a typo assigning `Platform: PlatformBrowserX`. Also seen when embedding esbuild via cgo and forgetting to map an upstream enum change after a re-vendor.

Related errors


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

Appendix: source

Thrown at pkg/api/api_impl.go:117

		parts = append(parts, config.PathTemplate{
			Data:        template,
			Placeholder: config.NoPlaceholder,
		})
	}

	return parts
}

func validatePlatform(value Platform) config.Platform {
	switch value {
	case PlatformDefault, PlatformBrowser:
		return config.PlatformBrowser
	case PlatformNode:
		return config.PlatformNode
	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")
	}
}

View on GitHub (pinned to f6058f8364)