{"record":{"id":"ac0704939813cf79","repo":"apache/cassandra","slug":"dynamic-first-syntax-error-message-from-parser-le","errorCode":null,"errorMessage":"(dynamic first syntax error message from parser/lexer)","messagePattern":"\\(dynamic first syntax error message from parser/lexer\\)","errorType":"validation","errorClass":"SyntaxException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/ErrorCollector.java","lineNumber":102,"sourceCode":"\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    public void syntaxError(BaseRecognizer recognizer, String errorMsg)\n    {\n        errorMsgs.add(errorMsg);\n    }\n\n    /**\n     * Throws the first syntax error found by the lexer or the parser if it exists.\n     *\n     * @throws SyntaxException the syntax error.\n     */\n    public void throwFirstSyntaxError() throws SyntaxException\n    {\n        if (!errorMsgs.isEmpty())\n            throw new SyntaxException(errorMsgs.getFirst());\n    }\n\n    /**\n     * Appends a query snippet to the message to help the user to understand the problem.\n     *\n     * @param parser the parser used to parse the query\n     * @param builder the <code>StringBuilder</code> used to build the error message\n     */\n    private void appendQuerySnippet(Parser parser, StringBuilder builder)\n    {\n        TokenStream tokenStream = parser.getTokenStream();\n        int index = tokenStream.index();\n        int size = tokenStream.size();\n\n        Token from = tokenStream.get(getSnippetFirstTokenIndex(index));\n        Token to = tokenStream.get(getSnippetLastTokenIndex(index, size));\n        Token offending = tokenStream.get(getOffendingTokenIndex(index, size));\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/ErrorCollector.java#L84-L120","documentation":"ErrorCollector.throwFirstSyntaxError rethrows the first syntax error accumulated by the ANTLR ErrorCollector as a SyntaxException. The message text is dynamic — produced by the parser/lexer (e.g. 'no viable alternative at input ...', 'missing ... at ...', 'extraneous input ...'). It is the detailed counterpart of the generic parseAny failure and is thrown by parseAnyUnhandled.","triggerScenarios":"Any CQL statement or fragment parsed via parseAnyUnhandled where ANTLR reports syntax errors: bad tokens, misplaced keywords, unterminated strings, invalid type names.","commonSituations":"Typos in CQL keywords; using reserved words as bare identifiers; copy-pasted SQL from other databases; version-specific grammar features used against an older Cassandra.","solutions":["Read the specific message: it names the offending input position — fix that token","Quote reserved keywords as identifiers with double quotes","Check the CQL grammar for your Cassandra version for unsupported syntax","Run the query in cqlsh to interactively iterate on the syntax"],"exampleFix":"// before\nString cql = \"SELECT count FROM tbl\"; // 'count' needs aggregation syntax\n// after\nString cql = \"SELECT count(*) FROM tbl\";","handlingStrategy":"validation","validationCode":"private static void requireCql(String cql) {\n    if (cql == null || cql.trim().isEmpty()) throw new IllegalArgumentException(\"Empty CQL\");\n    if (cql.chars().filter(c -> c == '\\'').count() % 2 != 0) throw new IllegalArgumentException(\"Unbalanced quotes\");\n    if (cql.chars().filter(c -> c == '(').count() != cql.chars().filter(c -> c == ')').count()) throw new IllegalArgumentException(\"Unbalanced parens\");\n}","typeGuard":null,"tryCatchPattern":"try { parse(cql); } catch (SyntaxException e) { throw new IllegalArgumentException(\"CQL syntax error: \" + e.getMessage(), e); }","preventionTips":["Quote reserved keywords with double quotes when used as identifiers","Validate syntax against the grammar of the target Cassandra version","Iterate queries in cqlsh before embedding them","Avoid hand-concatenating CQL from untrusted fragments"],"tags":["cql","syntax","antlr","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}