{"record":{"id":"c06f6d1e2279e74b","repo":"apache/iceberg","slug":"cannot-change-the-type-of-abovemax","errorCode":null,"errorMessage":"Cannot change the type of AboveMax","messagePattern":"Cannot change the type of AboveMax","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/expressions/Literals.java","lineNumber":188,"sourceCode":"    @SuppressWarnings(\"unchecked\")\n    public Comparator<C> comparator() {\n      return (Comparator<C>) CMP;\n    }\n  }\n\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","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/expressions/Literals.java#L170-L206","documentation":"AboveMax sentinel literals cannot be retyped: to(Type) throws UnsupportedOperationException because there is no concrete value to convert or overflow-check again. AboveMax already represents 'above every value of any type', so type conversion is meaningless.","triggerScenarios":"Calling to(Type) on Literals.aboveMax() or on a literal known to be an AboveMax sentinel — e.g. generic code that calls lit.to(expectedType) on every literal in an expression when rewriting predicates for a column's type.","commonSituations":"Generic predicate-rewriting code (e.g. adapting filters to projected/partition types) blindly converting literals; chained conversions where a first to() produced AboveMax and a second conversion is attempted.","solutions":["Skip conversion when the literal is already AboveMax/BelowMin (instanceof check) and pass the sentinel through unchanged","Guard generic to() calls with a type check for sentinel literals","Restructure conversion code so overflow to AboveMax terminates the conversion pipeline"],"exampleFix":"// before\nLiteral<T> retyped = (Literal<T>) lit.to(targetType); // throws for AboveMax\n// after\nLiteral<?> retyped = (lit instanceof Literals.AboveMax || lit instanceof Literals.BelowMin)\n    ? lit : lit.to(targetType);","handlingStrategy":"type-guard","validationCode":"if (lit instanceof Literals.AboveMax || lit instanceof Literals.BelowMin) {\n  // pass sentinel through; do not call to(Type)\n}","typeGuard":"static boolean retypable(Literal<?> lit) {\n  return !(lit instanceof Literals.AboveMax) && !(lit instanceof Literals.BelowMin);\n}","tryCatchPattern":"Literal<?> out;\ntry {\n  out = lit.to(targetType);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"Cannot change the type of AboveMax\")) {\n    out = lit; // sentinel is type-independent\n  } else {\n    throw e;\n  }\n}","preventionTips":["In generic literal-conversion loops, short-circuit on sentinel literals before calling to()","Design conversion pipelines so AboveMax/BelowMin terminate further conversions","Cover overflow cases in tests by converting oversized literals and asserting sentinel propagation"],"tags":["java","literals","sentinel-literal","type-conversion"],"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"}