evanw/esbuild · error · LexerPanic
Expected identifier after %q in namespaced JSX name
Error message
Expected identifier after %q in namespaced JSX name
What it means
In parseJSXNamespacedName, after a ':' JSX namespace separator the next token must be an identifier. If it is anything else, esbuild reports the partial namespace (e.g. 'foo:') and the position right after it, then aborts.
Source
Thrown at internal/js_parser/js_parser.go:5192
// Parse JSX namespaces. These are not supported by React or TypeScript
// but someone using JSX syntax in more obscure ways may find a use for
// them. A namespaced name is just always turned into a string so you
// can't use this feature to reference JavaScript identifiers.
if p.lexer.Token == js_lexer.TColon {
// Parse the colon
nameRange.Len = p.lexer.Range().End() - nameRange.Loc.Start
ns := name.String + ":"
p.lexer.NextInsideJSXElement()
// Parse the second identifier
if p.lexer.Token == js_lexer.TIdentifier {
nameRange.Len = p.lexer.Range().End() - nameRange.Loc.Start
ns += p.lexer.Identifier.String
p.lexer.NextInsideJSXElement()
} else {
p.log.AddError(&p.tracker, logger.Range{Loc: logger.Loc{Start: nameRange.End()}},
fmt.Sprintf("Expected identifier after %q in namespaced JSX name", ns))
panic(js_lexer.LexerPanic{})
}
return nameRange, js_lexer.MaybeSubstring{String: ns}
}
return nameRange, name
}
func tagOrFragmentHelpText(tag string) string {
if tag == "" {
return "fragment tag"
}
return fmt.Sprintf("%q tag", tag)
}
func (p *parser) parseJSXTag() (logger.Range, string, js_ast.Expr) {
loc := p.lexer.Loc()
// A missing tag is a fragmentView on GitHub (pinned to f6058f8364)
Solutions
- Provide an identifier after the colon, e.g. '<foo:bar />'.
- Remove the colon if a namespace was not intended.
- Use a dotted member form '<foo.bar />' to reference nested objects.
Example fix
// before <foo: /> // after <foo:bar />
Defensive patterns
Strategy: validation
Validate before calling
import "github.com/evanw/esbuild/pkg/api"
opts := api.TransformOptions{Loader: api.LoaderJSX}
res := api.Transform(jsx, opts)
for _, m := range res.Errors {
if strings.Contains(m.Text, "namespaced JSX name") {
// a ':' in a tag was not followed by an identifier
}
} Type guard
// Flag JSX tags like <foo:>, <foo:123>.
var reBadNs = regexp.MustCompile(`<[-A-Za-z0-9]+:(?![-A-Za-z0-9])`)
func jsxNamespaceMissingIdent(src string) bool { return reBadNs.MatchString(src) } Prevention
- Use the .jsx/.tsx loader so JSX parses as JSX.
- After a ':' in a JSX tag always supply an identifier, or drop the colon.
- Prefer dotted member tags over XML namespaces for nested components.
When it happens
Trigger: '<foo:>' or '<foo:123>' or '<foo:=bar />' — a ':' in a JSX tag/attribute name not followed by an identifier.
Common situations: Typing ':' instead of a name; auto-generated JSX with empty namespace segments; confusing XML-style namespaces with JSX member expressions.
Related errors
- Unexpected "-"
- Unexpected backslash in JSX element
- Unexpected end of file before a closing %s
- Unexpected newline before "=>"
- For loop initializers cannot start with "async of"
AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09).
Data as JSON: /api/errors/e49afa4b3c2fa4a7.
Report an issue: GitHub.