You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ur...@apache.org on 2026/09/18 10:05:34 UTC

(spark) branch master updated: [SPARK-59522][ML] Add descriptive messages to the bare require checks in InstanceBlock

This is an automated email from the ASF dual-hosted git repository.

uros-b pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 2ae8e4361b6f [SPARK-59522][ML] Add descriptive messages to the bare require checks in InstanceBlock
2ae8e4361b6f is described below

commit 2ae8e4361b6fbf04145d96e0d473b3706aafef0f
Author: Uros <22...@users.noreply.github.com>
AuthorDate: Fri Sep 18 10:05:20 2026 +0000

    [SPARK-59522][ML] Add descriptive messages to the bare require checks in InstanceBlock
    
    ### What changes were proposed in this pull request?
    
    `InstanceBlock` (in `Instance.scala`) has six `require(...)` invariant checks with no failure message, so a violation throws a bare `requirement failed`. This adds descriptive messages that interpolate the offending values:
    
    - the `InstanceBlock` constructor checks -- labels vs matrix rows, the matrix being transposed, and labels vs weights;
    - `InstanceBlock.blokifyWithMaxMemUsage` -- `maxMemUsage > 0` (both overloads) and the consistent-feature-dimension check.
    
    The conditions themselves are unchanged.
    
    ### Why are the changes needed?
    
    These checks guard internal invariants of the block-encoding path. A bare `requirement failed` is hard to act on; including the invariant and the actual values (lengths, feature dimensions, `maxMemUsage`) makes such failures diagnosable. This matches the messages already attached to sibling `require` checks elsewhere in `mllib`.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. `InstanceBlock` is `private[spark]`; this only changes the message of the `IllegalArgumentException` thrown on an internal invariant violation.
    
    ### How was this patch tested?
    
    Existing tests. This only adds messages to existing `require` checks; the conditions are unchanged, and each interpolated value is an expression already used in the corresponding condition, so this is a message-only edit.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8)
    
    Closes #58812 from uros-b/instance-require-messages.
    
    Authored-by: Uros <22...@users.noreply.github.com>
    Signed-off-by: Uros Bojanic <22...@users.noreply.github.com>
---
 .../scala/org/apache/spark/ml/feature/Instance.scala  | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/mllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala b/mllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala
index 2c7a9d2a91e6..af99d02f5dbc 100644
--- a/mllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala
+++ b/mllib/src/main/scala/org/apache/spark/ml/feature/Instance.scala
@@ -41,10 +41,15 @@ private[spark] case class InstanceBlock(
     labels: Array[Double],
     weights: Array[Double],
     matrix: Matrix) {
-  require(labels.length == matrix.numRows)
-  require(matrix.isTransposed)
+  require(labels.length == matrix.numRows,
+    s"The number of labels (${labels.length}) must match the number of matrix rows " +
+    s"(${matrix.numRows}).")
+  require(matrix.isTransposed,
+    "The matrix must be transposed (row-major for dense, CSR for sparse).")
   if (weights.nonEmpty) {
-    require(labels.length == weights.length)
+    require(labels.length == weights.length,
+      s"The number of weights (${weights.length}) must match the number of labels " +
+      s"(${labels.length}).")
   }
 
   def size: Int = labels.length
@@ -147,7 +152,7 @@ private[spark] object InstanceBlock {
   def blokifyWithMaxMemUsage(
       instanceIterator: Iterator[Instance],
       maxMemUsage: Long): Iterator[InstanceBlock] = {
-    require(maxMemUsage > 0)
+    require(maxMemUsage > 0, s"maxMemUsage must be positive but got $maxMemUsage.")
 
     new Iterator[InstanceBlock]() {
       private var numCols = -1L
@@ -164,7 +169,9 @@ private[spark] object InstanceBlock {
         while (instanceIterator.hasNext && blockMemUsage < maxMemUsage) {
           val instance = instanceIterator.next()
           if (numCols < 0L) numCols = instance.features.size
-          require(numCols == instance.features.size)
+          require(numCols == instance.features.size,
+            s"All instances must have the same number of features: expected $numCols " +
+            s"but got ${instance.features.size}.")
 
           buff += instance
           buffCnt += 1L
@@ -183,7 +190,7 @@ private[spark] object InstanceBlock {
   def blokifyWithMaxMemUsage(
       instances: RDD[Instance],
       maxMemUsage: Long): RDD[InstanceBlock] = {
-    require(maxMemUsage > 0)
+    require(maxMemUsage > 0, s"maxMemUsage must be positive but got $maxMemUsage.")
     instances.mapPartitions(iter => blokifyWithMaxMemUsage(iter, maxMemUsage))
   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org