apache/cassandra · error · IllegalArgumentException

could not parse update query

Error message

could not parse update query:${queryString}

What it means

dynamicConditionExists parses the profile's UPDATE statement with the internal CQL ANTLR parser to detect dynamic (bind-marker) conditions. If parsing fails with a RecognitionException, an IllegalArgumentException wrapping the queryString is thrown. This means the query defined in the YAML is not valid CQL UPDATE syntax as far as the server-side parser is concerned.

Solutions

  1. Fix the UPDATE statement syntax reported in the queryString; validate it with cqlsh first
  2. Check for Cassandra-version-specific grammar differences (e.g. LWT IF conditions syntax)
  3. Simplify the statement to isolate the offending fragment
  4. Escape identifiers/strings correctly in the YAML

Example fix

# before
queries:
  upd: UPDATE ks.t SET v = ? WHERE k = ? IF v =
# after
queries:
  upd: UPDATE ks.t SET v = ? WHERE k = ? IF v = ?
Defensive patterns

Strategy: validation

Validate before calling

// smoke-test the UPDATE in cqlsh / via session before stress
session.execute("UPDATE ks.t SET v = ? WHERE k = ? IF v = ?", 1, 1, 1);

Try / catch

try { profile.getQuery(name, ...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("could not parse update query")) log.error("Fix CQL syntax: {}", e.getMessage()); throw e; }

Prevention

When it happens

Trigger: A 'queries' or 'inserts' definition whose queryString is an UPDATE statement with syntax errors (missing SET clause, malformed IF conditions, invalid identifiers), processed via getQuery -> dynamicConditionExists.

Common situations: Hand-written CQL typos in YAML, using CQL features unsupported by this Cassandra version's grammar, unescaped identifiers or strings, copy-pasted SQL that is not CQL.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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

Appendix: source

Thrown at tools/stress/src/org/apache/cassandra/stress/StressProfile.java:453

    }

    static boolean dynamicConditionExists(PreparedStatement statement) throws IllegalArgumentException
    {
        if (statement == null)
            return false;

        if (!toUpperCaseLocalized(statement.getQueryString()).startsWith("UPDATE"))
            return false;

        ModificationStatement.Parsed modificationStatement;
        try
        {
            modificationStatement = CQLFragmentParser.parseAnyUnhandled(CqlParser::updateStatement,
                                                                        statement.getQueryString());
        }
        catch (RecognitionException e)
        {
            throw new IllegalArgumentException("could not parse update query:" + statement.getQueryString(), e);
        }

        /*
         * here we differentiate between static vs dynamic conditions:
         *  - static condition example: if col1 = NULL
         *  - dynamic condition example: if col1 = ?
         *  for static condition we don't have to replace value, no extra work involved.
         *  for dynamic condition we have to read existing db value and then
         *  use current db values during the update.
         */
        return modificationStatement.getConditions().stream().anyMatch(ColumnCondition.Raw::containsBindMarkers);
    }

    public Operation getBulkReadQueries(String name, Timer timer, StressSettings settings, TokenRangeIterator tokenRangeIterator, boolean isWarmup)
    {
        StressYaml.TokenRangeQueryDef def = tokenRangeQueries.get(name);
        if (def == null)
            throw new IllegalArgumentException("No bulk read query defined with name " + name);

View on GitHub (pinned to 88fd0f6a0e)