From 4941405b4f18663cb827e33cfad093c9619d8011 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 22 Aug 2026 16:18:27 -0500 Subject: [PATCH 1/2] Fix three malformed error messages Adjacent string literals concatenate in Python, and in two places the join produces text the author clearly did not intend: monai/networks/utils.py:443 pixelunshuffle() "...divisible by factor 2. , spatial shape is: [7, 8]" The second literal opens with ", " while the first already closed with ". ", so the rendered message carries a stray ". ,". monai/inferers/inferer.py:1776 LatentDiffusionInferer.__init__() "...autoencoder_latent_shape must be Noneand vice versa." No trailing space on the first literal, so two words run together. The third is a plain typo in the same family, a missing comma in a list of valid options, appearing in both the raised message and the docstring that documents it: monai/metrics/utils.py:104,144 do_metric_reduction() '[..., "mean_channel", "sum_channel" "none"].' Every sibling message in monai/losses/ writes this list fully comma-separated. All three are user-visible text only; no behaviour changes. Signed-off-by: Hans Johnson --- monai/inferers/inferer.py | 2 +- monai/metrics/utils.py | 4 ++-- monai/networks/utils.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/monai/inferers/inferer.py b/monai/inferers/inferer.py index bc55cef15c..ce8a0d468e 100644 --- a/monai/inferers/inferer.py +++ b/monai/inferers/inferer.py @@ -1773,7 +1773,7 @@ def __init__( super().__init__(scheduler=scheduler) self.scale_factor = scale_factor if (ldm_latent_shape is None) ^ (autoencoder_latent_shape is None): - raise ValueError("If ldm_latent_shape is None, autoencoder_latent_shape must be None" "and vice versa.") + raise ValueError("If ldm_latent_shape is None, autoencoder_latent_shape must be None and vice versa.") self.ldm_latent_shape = ldm_latent_shape self.autoencoder_latent_shape = autoencoder_latent_shape if self.ldm_latent_shape is not None and self.autoencoder_latent_shape is not None: diff --git a/monai/metrics/utils.py b/monai/metrics/utils.py index a5927a0a5b..a68d0c198d 100644 --- a/monai/metrics/utils.py +++ b/monai/metrics/utils.py @@ -101,7 +101,7 @@ def do_metric_reduction( Raises: ValueError: When ``reduction`` is not one of - ["mean", "sum", "mean_batch", "sum_batch", "mean_channel", "sum_channel" "none"]. + ["mean", "sum", "mean_batch", "sum_batch", "mean_channel", "sum_channel", "none"]. """ # some elements might be Nan (if ground truth y was missing (zeros)) @@ -141,7 +141,7 @@ def do_metric_reduction( elif reduction != MetricReduction.NONE: raise ValueError( f"Unsupported reduction: {reduction}, available options are " - '["mean", "sum", "mean_batch", "sum_batch", "mean_channel", "sum_channel" "none"].' + '["mean", "sum", "mean_batch", "sum_batch", "mean_channel", "sum_channel", "none"].' ) return f, not_nans diff --git a/monai/networks/utils.py b/monai/networks/utils.py index 0c40e5318b..83815fc543 100644 --- a/monai/networks/utils.py +++ b/monai/networks/utils.py @@ -440,7 +440,7 @@ def pixelunshuffle(x: torch.Tensor, spatial_dims: int, scale_factor: int) -> tor if any(d % factor != 0 for d in input_size[2:]): raise ValueError( - f"All spatial dimensions must be divisible by factor {factor}. " f", spatial shape is: {input_size[2:]}" + f"All spatial dimensions must be divisible by factor {factor}, spatial shape is: {input_size[2:]}" ) output_size = [batch_size, new_channels] + [d // factor for d in input_size[2:]] reshaped_size = [batch_size, channels] + sum([[d // factor, factor] for d in input_size[2:]], []) From dc8a3baae98c7738baf4de9e45cd7f549a833a98 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 22 Aug 2026 16:18:39 -0500 Subject: [PATCH 2/2] Cover pixelunshuffle()'s indivisible-dimension error path pixelunshuffle() raises ValueError when a spatial dimension is not divisible by the scale factor. Nothing exercised that branch: the five existing tests all use shapes that divide cleanly, so the guard clause and its message were never executed by the suite. That is why the malformed message corrected in the preceding commit survived from March 2025 without anyone noticing. This test covers that branch, and is written so it would have caught that specific defect. The wording of the assertion is load-bearing, not incidental, because the malformed code raises ValueError too: assertRaises(ValueError) alone passes on the broken message match "divisible by factor" passes on the broken message match "factor 2, spatial" fails on the broken message Only a pattern spanning the point where the two literals were joined can tell the two apart, so the assertion has to reach across it. Against the unfixed source it reports: AssertionError: "divisible by factor 2, spatial shape is: \[7, 8\]" does not match "All spatial dimensions must be divisible by factor 2. , spatial shape is: [7, 8]" The trade-off is that the test is coupled to the message text and will need updating if the message is reworded. That is the cost of pinning the defect; a looser assertion would pass either way and prove nothing. Kept as a separate commit so the text corrections can be reviewed, or reverted, independently of the new coverage. Signed-off-by: Hans Johnson --- tests/networks/utils/test_pixelunshuffle.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/networks/utils/test_pixelunshuffle.py b/tests/networks/utils/test_pixelunshuffle.py index 49b61440e5..cc9ae0d19f 100644 --- a/tests/networks/utils/test_pixelunshuffle.py +++ b/tests/networks/utils/test_pixelunshuffle.py @@ -40,6 +40,11 @@ def test_different_scale_factor(self): out = pixelunshuffle(x, spatial_dims=2, scale_factor=3) torch.testing.assert_close(out, torch.pixel_unshuffle(x, 3)) + def test_indivisible_spatial_dims(self): + x = torch.randn(1, 2, 7, 8) + with self.assertRaisesRegex(ValueError, r"divisible by factor 2, spatial shape is: \[7, 8\]"): + pixelunshuffle(x, spatial_dims=2, scale_factor=2) + def test_inverse_operation(self): x = torch.arange(4096).reshape(1, 8, 8, 8, 8) shuffled = pixelshuffle(x, spatial_dims=3, scale_factor=2)