{"record":{"id":"1fbcf4a72e21af40","repo":"apache/iceberg","slug":"abovemax-has-no-comparator","errorCode":null,"errorMessage":"AboveMax has no comparator","messagePattern":"AboveMax has no comparator","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/Literals.java","lineNumber":193,"sourceCode":"\n  static class AboveMax<T> implements Literal<T> {\n    private static final AboveMax INSTANCE = new AboveMax();\n\n    private AboveMax() {}\n\n    @Override\n    public T value() {\n      throw new UnsupportedOperationException(\"AboveMax has no value\");\n    }\n\n    @Override\n    public <X> Literal<X> to(Type type) {\n      throw new UnsupportedOperationException(\"Cannot change the type of AboveMax\");\n    }\n\n    @Override\n    public Comparator<T> comparator() {\n      throw new UnsupportedOperationException(\"AboveMax has no comparator\");\n    }\n\n    @Override\n    public String toString() {\n      return \"aboveMax\";\n    }\n  }\n\n  static class BelowMin<T> implements Literal<T> {\n    private static final BelowMin INSTANCE = new BelowMin();\n\n    private BelowMin() {}\n\n    @Override\n    public T value() {\n      throw new UnsupportedOperationException(\"BelowMin has no value\");\n    }\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/Literals.java#L175-L211","documentation":"AboveMax is a sentinel literal representing values larger than any representable value of a column's type (e.g. from literal conversion overflow). It exists only so predicate binding can detect 'value too large' and rewrite comparisons (e.g. LT becomes always-false). It carries no actual value, so obtaining a Comparator for it is meaningless and the library throws UnsupportedOperationException.","triggerScenarios":"Calling comparator() on the object returned by Literals.aboveMax(), typically after literal().to(type) returned aboveMax during predicate binding, or explicitly calling Literals.aboveMax().comparator() in custom expression code.","commonSituations":"Custom scan-planning or expression-rewriting code that generically calls literal.comparator() on every literal without excluding the aboveMax/belowMin sentinels.","solutions":["Exclude Literals.aboveMax() and Literals.belowMax() sentinels before calling comparator(); handle them with dedicated comparison logic","Check the literal class/sentinel identity first and branch to sentinel-aware logic","Use the bound expression API (Expressions/Binder) instead of manually comparing sentinel literals"],"exampleFix":"// before\nComparator<T> cmp = lit.comparator();\n// after\nif (lit == Literals.aboveMax() || lit == Literals.belowMin()) {\n  // handle sentinel: comparison result is decided by the operation, not a comparator\n} else {\n  Comparator<T> cmp = lit.comparator();\n}","handlingStrategy":"type-guard","validationCode":"if (lit == Literals.aboveMax() || lit == Literals.belowMin()) { throw new IllegalArgumentException(\"Sentinel literal has no comparator\"); }","typeGuard":"static boolean isSentinel(Literal<?> lit) { return lit == Literals.aboveMax() || lit == Literals.belowMin(); }","tryCatchPattern":"try { Comparator<?> cmp = lit.comparator(); } catch (UnsupportedOperationException e) { /* sentinel path: resolve via operation semantics */ }","preventionTips":["Always identity-check Literals.aboveMax()/belowMin() before generic literal operations","Prefer binding predicates via Binder instead of manual literal comparison","Unit-test custom visitors against predicates that trigger conversion overflow"],"tags":["expressions","literals","sentinel","unsupported"],"backgroundTag":"unsupported-operation","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"}