apache/cassandra · error · SyntaxException

(dynamic first syntax error message from parser/lexer)

Error message

(dynamic first syntax error message from parser/lexer)

What it means

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.

Source

Thrown at src/java/org/apache/cassandra/cql3/ErrorCollector.java:102

    /**
     * {@inheritDoc}
     */
    @Override
    public void syntaxError(BaseRecognizer recognizer, String errorMsg)
    {
        errorMsgs.add(errorMsg);
    }

    /**
     * Throws the first syntax error found by the lexer or the parser if it exists.
     *
     * @throws SyntaxException the syntax error.
     */
    public void throwFirstSyntaxError() throws SyntaxException
    {
        if (!errorMsgs.isEmpty())
            throw new SyntaxException(errorMsgs.getFirst());
    }

    /**
     * Appends a query snippet to the message to help the user to understand the problem.
     *
     * @param parser the parser used to parse the query
     * @param builder the <code>StringBuilder</code> used to build the error message
     */
    private void appendQuerySnippet(Parser parser, StringBuilder builder)
    {
        TokenStream tokenStream = parser.getTokenStream();
        int index = tokenStream.index();
        int size = tokenStream.size();

        Token from = tokenStream.get(getSnippetFirstTokenIndex(index));
        Token to = tokenStream.get(getSnippetLastTokenIndex(index, size));
        Token offending = tokenStream.get(getOffendingTokenIndex(index, size));

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Read the specific message: it names the offending input position — fix that token
  2. Quote reserved keywords as identifiers with double quotes
  3. Check the CQL grammar for your Cassandra version for unsupported syntax
  4. Run the query in cqlsh to interactively iterate on the syntax

Example fix

// before
String cql = "SELECT count FROM tbl"; // 'count' needs aggregation syntax
// after
String cql = "SELECT count(*) FROM tbl";
Defensive patterns

Strategy: validation

Validate before calling

private static void requireCql(String cql) {
    if (cql == null || cql.trim().isEmpty()) throw new IllegalArgumentException("Empty CQL");
    if (cql.chars().filter(c -> c == '\'').count() % 2 != 0) throw new IllegalArgumentException("Unbalanced quotes");
    if (cql.chars().filter(c -> c == '(').count() != cql.chars().filter(c -> c == ')').count()) throw new IllegalArgumentException("Unbalanced parens");
}

Try / catch

try { parse(cql); } catch (SyntaxException e) { throw new IllegalArgumentException("CQL syntax error: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Any CQL statement or fragment parsed via parseAnyUnhandled where ANTLR reports syntax errors: bad tokens, misplaced keywords, unterminated strings, invalid type names.

Common situations: 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.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ac0704939813cf79. Report an issue: GitHub.