{"record":{"id":"43245a4b49bf5e2c","repo":"apache/iceberg","slug":"startswith-expression-is-not-supported-by-the-visi","errorCode":null,"errorMessage":"startsWith expression is not supported by the visitor","messagePattern":"startsWith expression is not supported by the visitor","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/ExpressionVisitors.java","lineNumber":120,"sourceCode":"\n    public <T> R eq(BoundReference<T> ref, Literal<T> lit) {\n      return null;\n    }\n\n    public <T> R notEq(BoundReference<T> ref, Literal<T> lit) {\n      return null;\n    }\n\n    public <T> R in(BoundReference<T> ref, Set<T> literalSet) {\n      throw new UnsupportedOperationException(\"In expression is not supported by the visitor\");\n    }\n\n    public <T> R notIn(BoundReference<T> ref, Set<T> literalSet) {\n      throw new UnsupportedOperationException(\"notIn expression is not supported by the visitor\");\n    }\n\n    public <T> R startsWith(BoundReference<T> ref, Literal<T> lit) {\n      throw new UnsupportedOperationException(\n          \"startsWith expression is not supported by the visitor\");\n    }\n\n    public <T> R notStartsWith(BoundReference<T> ref, Literal<T> lit) {\n      throw new UnsupportedOperationException(\n          \"notStartsWith expression is not supported by the visitor\");\n    }\n\n    /**\n     * Handle a non-reference value in this visitor.\n     *\n     * <p>Visitors that require {@link BoundReference references} and not {@link Bound terms} can\n     * use this method to return a default value for expressions with non-references. The default\n     * implementation will throw a validation exception because the non-reference is not supported.\n     *\n     * @param term a non-reference bound expression\n     * @param <T> a Java return type\n     * @return a return value for the visitor","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/ExpressionVisitors.java#L102-L138","documentation":"The base visitor's default startsWith(BoundReference, Literal) throws UnsupportedOperationException; string-prefix predicates must be explicitly supported by a visitor. Thrown when a STARTS_WITH predicate reaches a visitor that does not override this method.","triggerScenarios":"Visiting an expression built with Expressions.startsWith(col, \"prefix\") with a visitor lacking a startsWith override, e.g. custom evaluators, older summary evaluators, or engines' pushdown filters hitting an un-updated visitor.","commonSituations":"Pushing LIKE 'abc%' style filters into custom visitors; third-party catalogs/evaluators written before the startsWith predicate existed.","solutions":["Override startsWith(BoundReference<T> ref, Literal<T> lit) in the visitor to evaluate/translate the prefix predicate","Catch UnsupportedOperationException and fall back to a conservative evaluation or reject the filter","Upgrade the visitor/evaluator implementation to a version supporting startsWith"],"exampleFix":"// before\n// no startsWith override -> default throws\n// after\n@Override\npublic <T> R startsWith(BoundReference<T> ref, Literal<T> lit) {\n  String prefix = (String) lit.value();\n  return evaluatePrefix(ref.column(), prefix);\n}","handlingStrategy":"try-catch","validationCode":"boolean hasStartsWith = exprOpScan(expr, op -> op == Expression.Operation.STARTS_WITH);","typeGuard":"static boolean isStartsWith(Predicate p) { return p.op() == Expression.Operation.STARTS_WITH; }","tryCatchPattern":"try {\n  return visitor.startsWith(ref, lit);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"startsWith expression is not supported\")) {\n    return conservativeResult(); // e.g. rows=true for evaluators\n  }\n  throw e;\n}","preventionTips":["Override startsWith and notStartsWith together for string columns","Translate LIKE 'x%' filters to startsWith explicitly before pushdown","Verify third-party evaluators list STARTS_WITH among supported operations"],"tags":["java","expressions","visitor","string-prefix"],"backgroundTag":"method-not-implemented","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}