{"record":{"id":"73eba9e11fd70495","repo":"apache/beam","slug":"bounds-should-be-in-ascending-order-without-duplicates","errorCode":null,"errorMessage":"bounds should be in ascending order without duplicates.","messagePattern":"bounds should be in ascending order without duplicates\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/combiners/src/main/java/org/apache/beam/sdk/extensions/combiners/Histogram.java","lineNumber":263,"sourceCode":"          width,\n          numBoundedBuckets,\n          BoundsInclusivity.LOWER_BOUND_INCLUSIVE_UPPER_BOUND_EXCLUSIVE);\n    }\n\n    /**\n     * Static factory method for defining bounds of explicit histogram.\n     *\n     * @param bounds array of explicit bounds of the buckets.\n     * @param boundsInclusivity enum value which defines if lower or upper bounds are\n     *     inclusive/exclusive.\n     */\n    public static BucketBounds explicit(List<Double> bounds, BoundsInclusivity boundsInclusivity) {\n      checkNotNull(bounds, \"the bounds array should not be null.\");\n      checkArgument(bounds.size() > 0, \"the bounds array should not be empty.\");\n\n      for (int i = 1; i < bounds.size(); i++) {\n        if (bounds.get(i - 1) >= bounds.get(i)) {\n          throw new IllegalArgumentException(\n              \"bounds should be in ascending order without duplicates.\");\n        }\n      }\n\n      return new AutoValue_Histogram_BucketBounds(ImmutableList.copyOf(bounds), boundsInclusivity);\n    }\n\n    /**\n     * Like {@link #explicit(List, BoundsInclusivity)}, but sets\n     * BoundsInclusivity.LOWER_BOUND_INCLUSIVE_UPPER_BOUND_EXCLUSIVE value for the boundsInclusivity\n     * parameter.\n     */\n    public static BucketBounds explicit(List<Double> bounds) {\n      return explicit(bounds, BoundsInclusivity.LOWER_BOUND_INCLUSIVE_UPPER_BOUND_EXCLUSIVE);\n    }\n  }\n\n  /**","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/combiners/src/main/java/org/apache/beam/sdk/extensions/combiners/Histogram.java#L245-L281","documentation":"Histogram BucketBounds.explicit() validates a user-provided list of bucket boundaries. Bounds must be strictly ascending because duplicate or non-monotonic bounds would make bucket ranges ambiguous or empty. If any bound is greater than or equal to the next one, IllegalArgumentException is thrown.","triggerScenarios":"Calling BucketBounds.explicit(List<Double> bounds, ...) with a list containing equal adjacent values (e.g. [1.0, 1.0, 2.0]) or descending values (e.g. [5.0, 1.0]).","commonSituations":"Building bounds programmatically with rounding that collapses distinct values to the same double; unsorted input from config files or user-supplied CSV data; duplicates introduced when merging boundary lists.","solutions":["Sort the bounds list and remove duplicates before calling explicit().","Ensure numeric types/formatting do not collapse distinct bounds to the same double.","Validate bounds with a pre-check loop before constructing BucketBounds."],"exampleFix":"// before\nBucketBounds.explicit(Arrays.asList(5.0, 1.0, 1.0), BoundsInclusivity.LOWER_BOUND_INCLUSIVE);\n// after\nList<Double> bounds = new TreeSet<>(Arrays.asList(5.0, 1.0, 1.0));\nBucketBounds.explicit(new ArrayList<>(bounds), BoundsInclusivity.LOWER_BOUND_INCLUSIVE);","handlingStrategy":"validation","validationCode":"List<Double> sorted = bounds.stream().distinct().sorted().collect(Collectors.toList());\nfor (int i = 1; i < sorted.size(); i++) {\n  if (!(sorted.get(i - 1) < sorted.get(i))) {\n    throw new IllegalArgumentException(\"bounds must be strictly ascending\");\n  }\n}\nBucketBounds.explicit(sorted, BoundsInclusivity.LOWER_BOUND_INCLUSIVE);","typeGuard":null,"tryCatchPattern":"try {\n  bucketBounds = BucketBounds.explicit(configuredBounds, inclusivity);\n} catch (IllegalArgumentException e) {\n  bucketBounds = BucketBounds.explicit(new ArrayList<>(new TreeSet<>(configuredBounds)), inclusivity);\n}","preventionTips":["Always derive bounds through TreeSet<Double> to guarantee sorted, unique values.","Validate config-file bounds at load time, before pipeline construction.","Beware rounding/precision loss collapsing adjacent bounds."],"tags":["java","illegal-argument","validation","histogram"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}