{"record":{"id":"f9b30c8892cb673a","repo":"evanw/esbuild","slug":"unexpected-f9b30c","errorCode":null,"errorMessage":"Unexpected \"-\"","messagePattern":"Unexpected \"-\"","errorType":"panic","errorClass":"LexerPanic","httpStatus":null,"severity":"error","filePath":"internal/js_parser/js_parser.go","lineNumber":5240,"sourceCode":"\n\t// Otherwise, this is an identifier\n\ttag := js_ast.Expr{Loc: loc, Data: &js_ast.EIdentifier{Ref: p.storeNameInRef(tagName)}}\n\n\t// Parse a member expression chain\n\tvar chain strings.Builder\n\tchain.WriteString(tagName.String)\n\tfor p.lexer.Token == js_lexer.TDot {\n\t\tp.lexer.NextInsideJSXElement()\n\t\tmemberRange := p.lexer.Range()\n\t\tmember := p.lexer.Identifier\n\t\tp.lexer.ExpectInsideJSXElement(js_lexer.TIdentifier)\n\n\t\t// Dashes are not allowed in member expression chains\n\t\tindex := strings.IndexByte(member.String, '-')\n\t\tif index >= 0 {\n\t\t\tp.log.AddError(&p.tracker, logger.Range{Loc: logger.Loc{Start: memberRange.Loc.Start + int32(index)}},\n\t\t\t\t\"Unexpected \\\"-\\\"\")\n\t\t\tpanic(js_lexer.LexerPanic{})\n\t\t}\n\n\t\tchain.WriteString(\".\" + member.String)\n\t\ttag = js_ast.Expr{Loc: loc, Data: p.dotOrMangledPropParse(tag, member, memberRange.Loc, js_ast.OptionalChainNone, wasOriginallyDot)}\n\t\ttagRange.Len = memberRange.Loc.Start + memberRange.Len - tagRange.Loc.Start\n\t}\n\n\treturn tagRange, chain.String(), tag\n}\n\nfunc (p *parser) parseJSXElement(loc logger.Loc) js_ast.Expr {\n\t// Keep track of the location of the first JSX element for error messages\n\tif p.firstJSXElementLoc.Start == -1 {\n\t\tp.firstJSXElementLoc = loc\n\t}\n\n\t// Parse the tag\n\tstartRange, startText, startTagOrNil := p.parseJSXTag()","sourceCodeStart":5222,"sourceCodeEnd":5258,"githubUrl":"https://github.com/evanw/esbuild/blob/f6058f8364fe7ab91ca57a83e02577ed74c9cae4/internal/js_parser/js_parser.go#L5222-L5258","documentation":"In parseJSXTag's member-expression chain ('<a.b.c>'), after a '.' the following identifier segment must not contain a '-'. Dashes are illegal in JavaScript identifiers, so a hyphenated segment after a dot is rejected.","triggerScenarios":"'<Foo.Bar-Baz />' or '<ui.button-1 />' — a dotted JSX tag whose member segment contains a hyphen.","commonSituations":"Trying to reach a kebab-case property via dot notation; confusing custom-element names ('<my-el>') with member access.","solutions":["Rename the member so it has no hyphen, e.g. '<ui.Button />'.","For kebab-case custom elements, use a single tag '<my-el>' (no dots).","Reference the component through a properly-named variable instead of a dotted path."],"exampleFix":"// before\n<ui.button-1 />\n// after\n<ui.Button />","handlingStrategy":"validation","validationCode":"import \"github.com/evanw/esbuild/pkg/api\"\nres := api.Transform(jsx, api.TransformOptions{Loader: api.LoaderJSX})\nfor _, m := range res.Errors {\n  if strings.Contains(m.Text, \"Unexpected \\\"-\\\"\") {\n    // a dotted JSX tag member contained a hyphen\n  }\n}","typeGuard":"// Flag dotted JSX tags whose member segment has a hyphen: <a.b-c>.\nvar reDashedMember = regexp.MustCompile(`<[-A-Za-z0-9]+(?:\\.[-A-Za-z0-9]*)*\\.[A-Za-z0-9]*-[A-Za-z0-9-]*`)\nfunc jsxTagHasDashedMember(src string) bool { return reDashedMember.MatchString(src) }","tryCatchPattern":null,"preventionTips":["Use PascalCase / camelCase for component object members used in dotted JSX tags.","Represent kebab-case elements as single tags <my-el>, not dotted paths.","Lint JSX tag names with eslint-plugin-react where possible."],"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"}