{"record":{"id":"31747c540fe7eb59","repo":"antlr/antlr4","slug":"lexernoviablealtexception-symbol","errorCode":null,"errorMessage":"LexerNoViableAltException + symbol","messagePattern":"LexerNoViableAltException \\+ symbol","errorType":"exception","errorClass":"LexerNoViableAltException","httpStatus":null,"severity":"error","filePath":"runtime/Go/antlr/v4/lexer_atn_simulator.go","lineNumber":267,"sourceCode":"\t\treturn ATNSimulatorError\n\t}\n\t// Add an edge from s to target DFA found/created for reach\n\treturn l.addDFAEdge(s, t, nil, reach)\n}\n\nfunc (l *LexerATNSimulator) failOrAccept(prevAccept *SimState, input CharStream, reach *ATNConfigSet, t int) int {\n\tif l.prevAccept.dfaState != nil {\n\t\tlexerActionExecutor := prevAccept.dfaState.lexerActionExecutor\n\t\tl.accept(input, lexerActionExecutor, l.startIndex, prevAccept.index, prevAccept.line, prevAccept.column)\n\t\treturn prevAccept.dfaState.prediction\n\t}\n\n\t// if no accept and EOF is first char, return EOF\n\tif t == TokenEOF && input.Index() == l.startIndex {\n\t\treturn TokenEOF\n\t}\n\n\tpanic(NewLexerNoViableAltException(l.recog, input, l.startIndex, reach))\n}\n\n// getReachableConfigSet when given a starting configuration set, figures out all [ATN] configurations\n// we can reach upon input t.\n//\n// Parameter reach is a return parameter.\nfunc (l *LexerATNSimulator) getReachableConfigSet(input CharStream, closure *ATNConfigSet, reach *ATNConfigSet, t int) {\n\t// l is used to Skip processing for configs which have a lower priority\n\t// than a runtimeConfig that already reached an accept state for the same rule\n\tSkipAlt := ATNInvalidAltNumber\n\n\tfor _, cfg := range closure.configs {\n\t\tcurrentAltReachedAcceptState := cfg.GetAlt() == SkipAlt\n\t\tif currentAltReachedAcceptState && cfg.passedThroughNonGreedyDecision {\n\t\t\tcontinue\n\t\t}\n\n\t\tif runtimeConfig.lexerATNSimulatorDebug {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Go/antlr/v4/lexer_atn_simulator.go#L249-L285","documentation":"NewLexerNoViableAltException is panicked by LexerATNSimulator.failOrAccept() in the Go runtime when the lexer DFA cannot match any rule from the current input position and the input is not EOF at the start index. It means the character(s) at startIndex are not recognized by any lexer rule in the current mode.","triggerScenarios":"Feeding input to the generated Go lexer containing a character with no matching lexer rule (e.g. '@' when no rule accepts it), or reaching a mode whose rules do not cover the next character. The Go runtime panics rather than throwing, so unrecovered it crashes the program.","commonSituations":"Missing catch-all lexer rule, unexpected unicode/whitespace in input, wrong mode after a pushMode, or feeding binary data to a text lexer.","solutions":["Add a catch-all lexer rule such as ERROR : . ; (or skip/tokenize unknown characters) in the grammar","Pre-validate or sanitize input before lexing","Wrap lexing in a recover() that converts the panic to an error, and report the offending line/column from the exception"],"exampleFix":"// grammar before\n// (no rule matches '@')\n\n// grammar after: catch-all rule\n// ERROR : . ;\n\n// Go guard\nfunc safeLex(l *antlr.Lexer, ts *antlr.CommonTokenStream) (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            if e, ok := r.(*antlr.LexerNoViableAltException); ok {\n                err = fmt.Errorf(\"bad input at line %d:%d\", e.GetLine(), e.GetColumn())\n                return\n            }\n            panic(r)\n        }\n    }()\n    ts.Fill()\n    return nil\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isLexerNoViableAlt(r interface{}) bool {\n    _, ok := r.(*antlr.LexerNoViableAltException)\n    return ok\n}","tryCatchPattern":"func safeFill(ts *antlr.CommonTokenStream) (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            if e, ok := r.(*antlr.LexerNoViableAltException); ok {\n                err = fmt.Errorf(\"lexer failed at line %d, col %d\", e.GetLine(), e.GetColumn())\n                return\n            }\n            panic(r)\n        }\n    }()\n    ts.Fill()\n    return nil\n}","preventionTips":["Add an ERROR : . ; catch-all rule to the lexer grammar","Pre-sanitize input for stray characters and control the lexer mode stack","Always recover() around lexing in Go; the runtime panics instead of throwing"],"tags":["antlr","go","lexer","panic"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}