{"record":{"id":"e49afa4b3c2fa4a7","repo":"evanw/esbuild","slug":"expected-identifier-after-q-in-namespaced-jsx-nam","errorCode":null,"errorMessage":"Expected identifier after %q in namespaced JSX name","messagePattern":"Expected identifier after %q in namespaced JSX name","errorType":"panic","errorClass":"LexerPanic","httpStatus":null,"severity":"error","filePath":"internal/js_parser/js_parser.go","lineNumber":5192,"sourceCode":"\t// Parse JSX namespaces. These are not supported by React or TypeScript\n\t// but someone using JSX syntax in more obscure ways may find a use for\n\t// them. A namespaced name is just always turned into a string so you\n\t// can't use this feature to reference JavaScript identifiers.\n\tif p.lexer.Token == js_lexer.TColon {\n\t\t// Parse the colon\n\t\tnameRange.Len = p.lexer.Range().End() - nameRange.Loc.Start\n\t\tns := name.String + \":\"\n\t\tp.lexer.NextInsideJSXElement()\n\n\t\t// Parse the second identifier\n\t\tif p.lexer.Token == js_lexer.TIdentifier {\n\t\t\tnameRange.Len = p.lexer.Range().End() - nameRange.Loc.Start\n\t\t\tns += p.lexer.Identifier.String\n\t\t\tp.lexer.NextInsideJSXElement()\n\t\t} else {\n\t\t\tp.log.AddError(&p.tracker, logger.Range{Loc: logger.Loc{Start: nameRange.End()}},\n\t\t\t\tfmt.Sprintf(\"Expected identifier after %q in namespaced JSX name\", ns))\n\t\t\tpanic(js_lexer.LexerPanic{})\n\t\t}\n\t\treturn nameRange, js_lexer.MaybeSubstring{String: ns}\n\t}\n\n\treturn nameRange, name\n}\n\nfunc tagOrFragmentHelpText(tag string) string {\n\tif tag == \"\" {\n\t\treturn \"fragment tag\"\n\t}\n\treturn fmt.Sprintf(\"%q tag\", tag)\n}\n\nfunc (p *parser) parseJSXTag() (logger.Range, string, js_ast.Expr) {\n\tloc := p.lexer.Loc()\n\n\t// A missing tag is a fragment","sourceCodeStart":5174,"sourceCodeEnd":5210,"githubUrl":"https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/js_parser/js_parser.go#L5174-L5210","documentation":"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.","triggerScenarios":"'<foo:>' or '<foo:123>' or '<foo:=bar />' — a ':' in a JSX tag/attribute name not followed by an identifier.","commonSituations":"Typing ':' instead of a name; auto-generated JSX with empty namespace segments; confusing XML-style namespaces with JSX member expressions.","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."],"exampleFix":"// before\n<foo: />\n// after\n<foo:bar />","handlingStrategy":"validation","validationCode":"import \"github.com/evanw/esbuild/pkg/api\"\nopts := api.TransformOptions{Loader: api.LoaderJSX}\nres := api.Transform(jsx, opts)\nfor _, m := range res.Errors {\n  if strings.Contains(m.Text, \"namespaced JSX name\") {\n    // a ':' in a tag was not followed by an identifier\n  }\n}","typeGuard":"// Flag JSX tags like <foo:>, <foo:123>.\nvar reBadNs = regexp.MustCompile(`<[-A-Za-z0-9]+:(?![-A-Za-z0-9])`)\nfunc jsxNamespaceMissingIdent(src string) bool { return reBadNs.MatchString(src) }","tryCatchPattern":null,"preventionTips":["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."],"tags":["syntax-error","parser","jsx"],"backgroundTag":null,"analyzedSha":"f6058f8364fe7ab91ca57a83e02577ed74c9cae4","analyzedAt":"2026-08-09T18:37:22.223Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}