evanw/esbuild · critical

Invalid legal comments

Error message

Invalid legal comments

What it means

A panic raised by validateLegalComments when the LegalComments value is not one of LegalCommentsDefault/None/Inline/EndOfFile/Linked/External. Reachable only through Go-API misuse that constructs an out-of-range enum value; the JS API's typed union prevents it.

Source

Thrown at pkg/api/api_impl.go:172

	switch value {
	case LegalCommentsDefault:
		if bundle {
			return config.LegalCommentsEndOfFile
		} else {
			return config.LegalCommentsInline
		}
	case LegalCommentsNone:
		return config.LegalCommentsNone
	case LegalCommentsInline:
		return config.LegalCommentsInline
	case LegalCommentsEndOfFile:
		return config.LegalCommentsEndOfFile
	case LegalCommentsLinked:
		return config.LegalCommentsLinkedWithComment
	case LegalCommentsExternal:
		return config.LegalCommentsExternalWithoutComment
	default:
		panic("Invalid legal comments")
	}
}

func validateColor(value StderrColor) logger.UseColor {
	switch value {
	case ColorIfTerminal:
		return logger.ColorIfTerminal
	case ColorNever:
		return logger.ColorNever
	case ColorAlways:
		return logger.ColorAlways
	default:
		panic("Invalid color")
	}
}

func validateLogLevel(value LogLevel) logger.LogLevel {
	switch value {

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Use only the documented LegalComments constants.
  2. Guard external deserialization with a switch defaulting to LegalCommentsDefault.
  3. Avoid casting raw integers to LegalComments.
  4. Pin esbuild to a single version across your dependency graph.

Example fix

// before
opts.LegalComments = api.LegalComments(9)

// after
opts.LegalComments = api.LegalCommentsEndOfFile
Defensive patterns

Strategy: type-guard

Validate before calling

func validLegalComments(l api.LegalComments) bool {
  switch l {
  case api.LegalCommentsDefault, api.LegalCommentsNone, api.LegalCommentsInline, api.LegalCommentsEndOfFile, api.LegalCommentsLinked, api.LegalCommentsExternal:
    return true
  }
  return false
}

Type guard

type LegalComments = 'none' | 'inline' | 'eof' | 'linked' | 'external'
function isLegalComments(v: unknown): v is LegalComments {
  return ['none','inline','eof','linked','external'].includes(v as any)
}

Prevention

When it happens

Trigger: Go API: BuildOptions.LegalComments = LegalComments(9). The JS API maps the option's string union to valid constants internally and cannot trigger the panic.

Common situations: Reflective config loading; vendoring drift between fork and upstream enum ordinals; unsafe struct copying across esbuild versions.

Related errors


AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03). Data as JSON: /data/errors/d8ab793b8cd64def.json. Report an issue: GitHub.