apache/seatunnel · error · RuntimeException
Failed to parse select columns:
Error message
Failed to parse select columns:
What it means
ExpressionUtils.parseSelectColumns() parses a SELECT SQL string with JSQLParser to extract select items. If the SQL cannot be parsed (JSQLParserException), it wraps it in a RuntimeException with this message. Typically this is used for delete-SQL conversion, so a malformed query breaks expression translation.
Source
Thrown at seatunnel-connectors-v2/connector-iceberg/src/main/java/org/apache/seatunnel/connectors/seatunnel/iceberg/utils/ExpressionUtils.java:87
new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(ISO_LOCAL_TIME)
.toFormatter();
public static List<String> parseSelectColumns(String selectQuery) {
if (StringUtils.isNotBlank(selectQuery)) {
try {
Statement statement = CCJSqlParserUtil.parse(selectQuery);
PlainSelect select = (PlainSelect) statement;
if (CollectionUtils.isNotEmpty(select.getSelectItems())) {
return select.getSelectItems().stream()
.map(selectItem -> selectItem.toString())
.collect(Collectors.toList());
}
} catch (JSQLParserException e) {
throw new RuntimeException("Failed to parse select columns: " + e.getMessage());
}
}
return new ArrayList<>();
}
public static Expression parseWhereClauseToIcebergExpression(String selectQuery)
throws JSQLParserException {
// use the JsqlParser to parse the where clause
Statement statement = CCJSqlParserUtil.parse(selectQuery);
PlainSelect select = (PlainSelect) statement;
return convert(select.getWhere(), null);
}
public static Expression convertDeleteSQL(String sql) throws JSQLParserException {
Statement statement = CCJSqlParserUtil.parse(sql);
Delete delete = (Delete) statement;
return convert(delete.getWhere(), null);
}View on GitHub (pinned to cf67b549a7)
Solutions
- Print the wrapped cause (e.getMessage() already includes JSQLParser's error) and fix the SQL syntax
- Simplify the query — remove dialect-specific syntax (e.g. functions, comments) that JSQLParser doesn't support
- Ensure a valid SELECT statement is passed (SELECT cols FROM table), not a bare column list or WHERE clause
- Check the JSQLParser version bundled with the connector supports your SQL constructs; upgrade if needed
Example fix
// before
parseSelectColumns("FROM my_table")
// after
parseSelectColumns("SELECT * FROM my_table") Defensive patterns
Strategy: validation
Validate before calling
// Basic sanity check before invoking the parser
if (sql == null || !sql.trim().toLowerCase().startsWith("select")) throw new IllegalArgumentException("expected a SELECT statement"); Try / catch
try { cols = parseSelectColumns(sql); } catch (RuntimeException e) { if (e.getMessage().startsWith("Failed to parse select columns")) { /* fix SQL, log e.getMessage() for parser detail */ } throw e; } Prevention
- Validate SQL syntax before passing to expression utilities
- Avoid dialect-specific syntax the bundled JSQLParser can't parse
- Always pass a complete SELECT statement
When it happens
Trigger: Passing SQL that JSQLParser cannot parse into parseSelectColumns — syntax errors, unsupported SQL dialect constructs, missing clauses, or non-SELECT statements.
Common situations: Hand-written delete/select queries with typos; dialect-specific SQL (backticks, functions) unsupported by the bundled JSQLParser version; passing a table name or WHERE-only fragment instead of a full SELECT.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The source table[%s] is not found
- Unsupported syntax: %s
- Insert sql must not have columns
- Insert sql must have select statement
- Source table must be specified in SQL: <insertSql>
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/bc0f00c47daf23e1.
Report an issue: GitHub.