From f9a90f3cc927afcd62d5e17929392abef2edbb5d Mon Sep 17 00:00:00 2001 From: Martin Hauser Date: Tue, 21 Jul 2026 17:27:54 +0200 Subject: [PATCH] fix(dcim): Correct format placeholder in Cluster location validation error (#22725) Changes 'site' to 'location' in the error message format string to match the actual parameter name being passed. Adds regression test coverage to verify the error message displays the correct location name. Fixes #22717 --- netbox/dcim/models/devices.py | 2 +- netbox/dcim/tests/test_models.py | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 88d094b97..e8f82d58e 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -946,7 +946,7 @@ class Device( if self.cluster and self.cluster._location is not None and self.cluster._location != self.location: raise ValidationError({ 'cluster': _("The assigned cluster belongs to a different location ({location})").format( - site=self.cluster._location + location=self.cluster._location ) }) diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index a4d6c7bf0..d450049a6 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -855,6 +855,50 @@ class DeviceTestCase(TestCase): cluster=clusters[1] ).full_clean() + @tag('regression') # Ref: #22717 + def test_device_mismatched_location_cluster(self): + """ + A cluster scoped to a different location than the device must be rejected + with a field validation error naming that location. + """ + site = Site.objects.create(name='Site 1', slug='site-1') + locations = ( + Location(site=site, name='Location A', slug='location-a'), + Location(site=site, name='Location B', slug='location-b'), + ) + for location in locations: + location.save() + + cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + cluster = Cluster.objects.create(name='Cluster 1', type=cluster_type, scope=locations[0]) + + device_type = DeviceType.objects.first() + device_role = DeviceRole.objects.first() + + # Device in the cluster's location should pass + Device( + name='device1', + site=site, + location=locations[0], + device_type=device_type, + role=device_role, + cluster=cluster + ).full_clean() + + # Device in a different location of the same site should fail + with self.assertRaisesMessage( + ValidationError, + 'The assigned cluster belongs to a different location (Location A)' + ): + Device( + name='device1', + site=site, + location=locations[1], + device_type=device_type, + role=device_role, + cluster=cluster + ).full_clean() + class DeviceBayTestCase(TestCase):