{"record":{"id":"46868b7cf601a4ac","repo":"apache/beam","slug":"threshold-must-be-a-positive-integer","errorCode":null,"errorMessage":"Threshold must be a positive integer","messagePattern":"Threshold must be a positive integer","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/BundleLifter.java","lineNumber":139,"sourceCode":"  }\n\n  private BundleLifter(TupleTag<T> smallBatchTag, TupleTag<T> largeBatchTag, int threshold) {\n    this(smallBatchTag, largeBatchTag, threshold, x -> 1);\n  }\n\n  private BundleLifter(\n      TupleTag<T> smallBatchTag,\n      TupleTag<T> largeBatchTag,\n      int threshold,\n      SerializableFunction<T, Integer> elementSizer) {\n    if (smallBatchTag == null || largeBatchTag == null) {\n      throw new IllegalArgumentException(\"smallBatchTag and largeBatchTag must not be null\");\n    }\n    if (smallBatchTag.getId().equals(largeBatchTag.getId())) {\n      throw new IllegalArgumentException(\"smallBatchTag and largeBatchTag must be different\");\n    }\n    if (threshold <= 0) {\n      throw new IllegalArgumentException(\"Threshold must be a positive integer\");\n    }\n\n    this.smallBatchTag = smallBatchTag;\n    this.largeBatchTag = largeBatchTag;\n    this.threshold = threshold;\n    this.elementSizer = elementSizer;\n  }\n\n  public static <T> BundleLifter<T> of(\n      TupleTag<T> smallBatchTag, TupleTag<T> largeBatchTag, int threshold) {\n    return new BundleLifter<>(smallBatchTag, largeBatchTag, threshold);\n  }\n\n  public static <T> BundleLifter<T> of(\n      TupleTag<T> smallBatchTag,\n      TupleTag<T> largeBatchTag,\n      int threshold,\n      SerializableFunction<T, Integer> elementSizer) {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/BundleLifter.java#L121-L157","documentation":"BundleLifter's constructor requires the batch size threshold to be strictly positive. The threshold decides when a batch is treated as large; zero or negative values would make batching logic nonsensical, so the constructor rejects them.","triggerScenarios":"Calling new BundleLifter<>(...) with threshold <= 0 — e.g., passing 0, a negative value, or a value read from pipeline options/default configuration that was never validated.","commonSituations":"A pipeline option for batch threshold defaulting to 0 ('disabled' intended); computing threshold dynamically (e.g., targetSize - overhead) yielding <= 0; user passing negative values in configuration files.","solutions":["Pass a threshold of at least 1 when constructing BundleLifter.","Validate the pipeline option/config value before constructing BundleLifter and fail with a clear message.","Fix the default value in your options class to a sensible positive number."],"exampleFix":"// before\nint threshold = options.getBatchThreshold(); // 0\nBundleLifter<T> lifter = new BundleLifter<>(td, cls, supplier, smallTag, largeTag, threshold, sizer);\n// after\nint threshold = Math.max(1, options.getBatchThreshold());\nBundleLifter<T> lifter = new BundleLifter<>(td, cls, supplier, smallTag, largeTag, threshold, sizer);","handlingStrategy":"validation","validationCode":"checkArgument(threshold > 0, \"Batch threshold must be positive, got %s\", threshold);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate pipeline options for batch threshold before pipeline construction.","Set a positive default (e.g., 100) in your options class instead of 0.","Clamp computed thresholds with Math.max(1, value)."],"tags":["java","constructor-validation","apache-beam","iceberg"],"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-14T11:17:12.474Z"}