apache/beam · error · ParseException

Unable to parse query %s

Error message

Unable to parse query %s

What it means

Beam SQL's CalciteQueryPlanner.parse() wraps Apache Calcite's SqlParseException from the planner.parse() call into a ParseException with the original SQL statement in the message. It means the SQL string is syntactically invalid (or uses syntax this Calcite dialect/parser config does not accept), not that the query failed schema validation. The planner is closed in a finally block, so the parse failure does not leak resources.

Source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/CalciteQueryPlanner.java:181

                // Session-scoped custom operators (e.g. registered scalar Python UDFs that must
                // declare a non-fixed VARIADIC operand checker). Chained first and held by
                // reference, so operators added to the connection's table after the planner is
                // built
                // still resolve. Placing it ahead of the catalogReader avoids the duplicate
                // fixed-parameter overload that schema auto-wrapping would otherwise create.
                connection.getExtraOperatorTable(), opTab0, catalogReader))
        .sqlToRelConverterConfig(sqlToRelConfig)
        .build();
  }

  /** Parse input SQL query, and return a {@link SqlNode} as grammar tree. */
  @Override
  public SqlNode parse(String sqlStatement) throws ParseException {
    SqlNode parsed;
    try {
      parsed = planner.parse(sqlStatement);
    } catch (SqlParseException e) {
      throw new ParseException(String.format("Unable to parse query %s", sqlStatement), e);
    } finally {
      planner.close();
    }
    return parsed;
  }

  /**
   * It parses and validate the input query, then convert into a {@link BeamRelNode} tree. Note that
   * query parameters are not yet supported.
   */
  @Override
  public BeamRelNode convertToBeamRel(String sqlStatement, QueryParameters queryParameters)
      throws ParseException, SqlConversionException {
    Preconditions.checkArgument(
        queryParameters.getKind() == Kind.NONE || queryParameters.getKind() == Kind.POSITIONAL,
        "Beam SQL Calcite dialect only supports positional query parameters.");
    BeamRelNode beamRelNode;
    try {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Fix the SQL syntax reported by the wrapped SqlParseException's cause (line/column info is in the cause).
  2. Check Beam SQL documentation for supported syntax and rewrite unsupported constructs.
  3. If the query is built dynamically, print the final sqlStatement from the message and run it through a SQL linter.
  4. Upgrade the Beam version if the syntax is standard SQL recently added to Beam SQL.

Example fix

// before
pipeline.apply(SqlTransform.query("SELCT * FROM t"));
// after
pipeline.apply(SqlTransform.query("SELECT * FROM t"));
Defensive patterns

Strategy: try-catch

Validate before calling

// basic sanity check before submitting
if (sql == null || sql.trim().isEmpty()) {
  throw new IllegalArgumentException("Empty SQL statement");
}
// cheap lint: balanced parens outside string literals
int opens = 0; boolean inStr = false;
for (char c : sql.toCharArray()) {
  if (c == '\'') inStr = !inStr;
  else if (!inStr && c == '(') opens++;
  else if (!inStr && c == ')') opens--;
}
if (opens != 0) throw new IllegalArgumentException("Unbalanced parentheses in SQL");

Type guard

boolean isLikelyValidSql(String sql) {
  return sql != null && !sql.trim().isEmpty();
}

Try / catch

try {
  SqlNode parsed = planner.parse(sqlStatement);
} catch (ParseException e) {
  LOG.error("SQL syntax error for query [{}] cause: {}", sqlStatement, e.getCause().getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Calling parse(sqlStatement) (or convertToBeamRel) with SQL that Calcite's parser cannot tokenize or parse: typos, unbalanced parentheses/quotes, unsupported syntax outside Beam SQL's dialect, or a non-SQL string passed as a statement.

Common situations: Dynamically built SQL with missing fragments; pasting dialect-specific SQL (T-SQL/PL-SQL) that Calcite's default dialect rejects; BOM or hidden characters in the query string; Beam version not yet supporting a newly used SQL feature.

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/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/fb328cb3cdeefe2d. Report an issue: GitHub.