evanw/esbuild · error · LexerPanic

Unexpected "..."

Error message

Unexpected "..."

What it means

In a parenthesized expression that esbuild concluded is not an arrow function, a spread '...' was present (spreadRange non-empty). Spread is only valid in arrow arguments, calls, or array literals, so as a bare parenthesized element it is illegal.

Source

Thrown at internal/js_parser/js_parser.go:3350

	}

	// Are these arguments for a call to a function named "async"?
	if isAsync {
		p.logExprErrors(&errors)
		async := js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{
			Ref: p.storeNameInRef(js_lexer.MaybeSubstring{String: "async"})}}
		return js_ast.Expr{Loc: loc, Data: &js_ast.ECall{
			Target: async,
			Args:   items,
		}}
	}

	// Is this a chain of expressions and comma operators?
	if len(items) > 0 {
		p.logExprErrors(&errors)
		if spreadRange.Len > 0 {
			p.log.AddError(&p.tracker, spreadRange, "Unexpected \"...\"")
			panic(js_lexer.LexerPanic{})
		}
		value := js_ast.JoinAllWithComma(items)
		p.markExprAsParenthesized(value, loc, isAsync)
		return value
	}

	// Indicate that we expected an arrow function
	p.lexer.Expected(js_lexer.TEqualsGreaterThan)
	return js_ast.Expr{}
}

type invalidLog struct {
	invalidTokens  []logger.Range
	syntaxFeatures []syntaxFeature
}

type syntaxFeature struct {
	feature compat.JSFeature

View on GitHub (pinned to f6058f8364)

Solutions

  1. Add '=> body' to turn it into an arrow function.
  2. Remove the '...' if spread was not intended as a parameter.
  3. Move the spread into a call/array context where it is legal.

Example fix

// before
const f = (...a)
// after
const f = (...a) => a
Defensive patterns

Strategy: validation

Validate before calling

import "github.com/evanw/esbuild/pkg/api"
res := api.Transform(src, api.TransformOptions{Loader: api.LoaderJS})
for _, m := range res.Errors {
  if strings.Contains(m.Text, "Unexpected \"...\"") {
    // spread used outside an arrow/call/array context
  }
}

Prevention

When it happens

Trigger: '(...args)' or '(...a)' used as a standalone parenthesized expression without a following '=>'.

Common situations: Forgot the '=>'; copy-pasting a function signature; partial refactor that dropped the arrow body.

Related errors


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