{"record":{"id":"77c899997af21829","repo":"apache/beam","slug":"encountered-an-error-when-parsing-filter-filter","errorCode":null,"errorMessage":"Encountered an error when parsing filter: '{filter}'","messagePattern":"Encountered an error when parsing filter: '(.+?)'","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/FilterUtils.java","lineNumber":106,"sourceCode":"  public static final Set<SqlKind> SUPPORTED_OPS = FILTERS.keySet();\n\n  /**\n   * Parses a SQL filter expression string and returns a set of all field names referenced within\n   * it.\n   */\n  static Set<String> getReferencedFieldNames(@Nullable String filter) {\n    if (filter == null || filter.trim().isEmpty()) {\n      return new HashSet<>();\n    }\n\n    SqlParser parser = SqlParser.create(filter);\n    try {\n      SqlNode expression = parser.parseExpression();\n      Set<String> fieldNames = new HashSet<>();\n      extractFieldNames(expression, fieldNames);\n      return fieldNames;\n    } catch (Exception exception) {\n      throw new RuntimeException(\n          String.format(\"Encountered an error when parsing filter: '%s'\", filter), exception);\n    }\n  }\n\n  private static void extractFieldNames(SqlNode node, Set<String> fieldNames) {\n    if (node instanceof SqlIdentifier) {\n      fieldNames.add(getFieldName((SqlIdentifier) node));\n    } else if (node instanceof SqlBasicCall) {\n      // recursively check operands\n      SqlBasicCall call = (SqlBasicCall) node;\n      for (SqlNode operand : call.getOperandList()) {\n        extractFieldNames(operand, fieldNames);\n      }\n    } else if (node instanceof SqlNodeList) {\n      // For IN clauses, the right-hand side is a SqlNodeList, so iterate through its elements\n      SqlNodeList nodeList = (SqlNodeList) node;\n      for (SqlNode element : nodeList.getList()) {\n        if (element != null) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/FilterUtils.java#L88-L124","documentation":"FilterUtils.getReferencedFieldNames parses a SQL filter expression with Calcite's SqlParser to collect the field names it references. Any parse failure is wrapped in a RuntimeException with the offending filter text, chaining the original exception as the cause.","triggerScenarios":"Calling FilterUtils.getReferencedFieldNames(filter, ...) with a string that is not a valid SQL expression — e.g., a filter in Iceberg's string syntax that Calcite cannot parse, or a truncated/malformed predicate string.","commonSituations":"Filters built for a different SQL dialect; string filters pasted from Iceberg/Spark syntax that differ from Calcite's grammar; typos like missing quotes around literals or unbalanced parentheses.","solutions":["Inspect the chained cause (exception.getCause()) to see the exact SqlParseException and fix the filter string accordingly.","Rewrite the filter to a Calcite-parseable SQL expression (balanced parens, quoted literals).","Prefer passing Expression objects or validated filter strings into the pipeline rather than hand-written SQL strings."],"exampleFix":"// before\ngetReferencedFieldNames(\"ts >= 2024-01-01 AND id IN (1,2\", schema);\n// after\ngetReferencedFieldNames(\"ts >= '2024-01-01' AND id IN (1, 2)\", schema);","handlingStrategy":"try-catch","validationCode":"try { SqlParser.create(filter).parseExpression(); } catch (Exception e) { throw new IllegalArgumentException(\"Invalid filter: \" + filter, e); }","typeGuard":null,"tryCatchPattern":"try {\n  Set<String> fields = FilterUtils.getReferencedFieldNames(filter, schema);\n} catch (RuntimeException e) {\n  LOG.error(\"Cannot parse filter '{}': {}\", filter, e.getCause());\n  // fall back to unfiltered read or abort pipeline\n}","preventionTips":["Validate filter strings with a test parse before submitting pipelines.","Use single quotes for SQL string literals and balance parentheses.","Store filters as Iceberg Expressions instead of raw strings when possible."],"tags":["java","sql-parsing","calcite","apache-beam","iceberg"],"backgroundTag":"invalid-argument-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}