{"record":{"id":"9eceeff9ab3ae137","repo":"apache/iceberg","slug":"no-other-bound-is-defined","errorCode":null,"errorMessage":"No other bound is defined.","messagePattern":"No other bound is defined\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"orc/src/main/java/org/apache/iceberg/orc/OrcMetrics.java","lineNumber":372,"sourceCode":"        || type.typeId() != Type.TypeID.STRING\n        || value == null) {\n      return value;\n    }\n\n    CharSequence charSequence = (CharSequence) value;\n    MetricsModes.Truncate truncateMode = (MetricsModes.Truncate) metricsMode;\n    int truncateLength = truncateMode.length();\n\n    switch (bound) {\n      case UPPER:\n        return Optional.ofNullable(\n                UnicodeUtil.truncateStringMax(Literal.of(charSequence), truncateLength))\n            .map(Literal::value)\n            .orElse(charSequence);\n      case LOWER:\n        return UnicodeUtil.truncateStringMin(Literal.of(charSequence), truncateLength).value();\n      default:\n        throw new RuntimeException(\"No other bound is defined.\");\n    }\n  }\n\n  private static Set<Integer> statsColumns(TypeDescription schema) {\n    return OrcSchemaVisitor.visit(schema, new StatsColumnsVisitor());\n  }\n\n  private static class StatsColumnsVisitor extends OrcSchemaVisitor<Set<Integer>> {\n    @Override\n    public Set<Integer> record(\n        TypeDescription record, List<String> names, List<Set<Integer>> fields) {\n      ImmutableSet.Builder<Integer> result = ImmutableSet.builder();\n      fields.stream().filter(Objects::nonNull).forEach(result::addAll);\n      record.getChildren().stream()\n          .map(ORCSchemaUtil::icebergID)\n          .filter(Optional::isPresent)\n          .map(Optional::get)\n          .forEach(result::add);","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/orc/src/main/java/org/apache/iceberg/orc/OrcMetrics.java#L354-L390","documentation":"OrcMetrics.truncateIfNeeded truncates ORC string statistics to an Iceberg bound (BELOW/ABOVE) when converting min/max stats to Iceberg literals. The switch over the LowerBound/UpperBound enum has cases for LOWER and UPPER only; any other value falls into the default branch and throws. Since only two bounds exist, this indicates a programming error or a future enum value not yet handled.","triggerScenarios":"Calling fromOrcMin or fromOrcMax on OrcMetrics with a CharSequence stat whose bound value is neither Bound.Is BELOW(lower) case nor UPPER case — i.e. a new/unmapped Bound enum constant reaching truncateIfNeeded's default branch.","commonSituations":"Iceberg version drift where a new Bound constant was added but OrcMetrics was not updated; custom code invoking the private path via reflection or a patched fork passing an unexpected bound.","solutions":["Upgrade to a current Iceberg version where the bound switch is complete; this path is only reachable with a mismatched or patched build.","Check that you are not mixing iceberg-orc and iceberg-core JARs from different versions on the classpath.","If you maintain a fork, add a case for the new Bound constant (or replace RuntimeException with UnsupportedOperationException for consistency) and a unit test covering both bounds."],"exampleFix":"// before\ndefault:\n  throw new RuntimeException(\"No other bound is defined.\");\n// after\ndefault:\n  throw new UnsupportedOperationException(\"Unhandled bound: \" + bound);\n// or add the missing case:\ncase NEW_BOUND:\n  return ...;","handlingStrategy":"type-guard","validationCode":"if (bound != Bound.Is.LOWER && bound != Bound.Is.UPPER) { throw new IllegalArgumentException(\"Unsupported bound: \" + bound); }","typeGuard":"static boolean isSupportedBound(org.apache.iceberg.expressions.Bound<?> b) { return b instanceof org.apache.iceberg.expressions.Bound.Is; }","tryCatchPattern":"try { stats = OrcMetrics.fromOrcMin(...); } catch (RuntimeException e) { if (e.getMessage().contains(\"No other bound\")) { skipStats(); } else throw e; }","preventionTips":["Keep iceberg-orc and iceberg-core at the same version","Never patch Bound enums in forks without updating OrcMetrics","Add exhaustive-switch tests covering both bounds"],"tags":["orc","metrics","enum-exhaustiveness","stats-conversion"],"backgroundTag":"invalid-enum-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}