diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroConProductosActivosException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroConProductosActivosException.cs
new file mode 100644
index 0000000..e55fb34
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroConProductosActivosException.cs
@@ -0,0 +1,17 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when attempting to soft-delete a Rubro that still has active Products referencing it via RubroId. → HTTP 409
+///
+public sealed class RubroConProductosActivosException : DomainException
+{
+ public int RubroId { get; }
+ public int ProductosActivosCount { get; }
+
+ public RubroConProductosActivosException(int rubroId, int productosActivosCount)
+ : base($"No se puede desactivar el rubro {rubroId}: tiene {productosActivosCount} producto(s) activo(s) referenciándolo.")
+ {
+ RubroId = rubroId;
+ ProductosActivosCount = productosActivosCount;
+ }
+}
diff --git a/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroConProductosActivosExceptionTests.cs b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroConProductosActivosExceptionTests.cs
new file mode 100644
index 0000000..b8c433a
--- /dev/null
+++ b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroConProductosActivosExceptionTests.cs
@@ -0,0 +1,27 @@
+using FluentAssertions;
+using SIGCM2.Domain.Exceptions;
+
+namespace SIGCM2.Application.Tests.Domain.Rubros;
+
+public class RubroConProductosActivosExceptionTests
+{
+ [Fact]
+ public void Constructor_SetsPropertiesAndMessage()
+ {
+ var ex = new RubroConProductosActivosException(rubroId: 7, productosActivosCount: 3);
+
+ ex.RubroId.Should().Be(7);
+ ex.ProductosActivosCount.Should().Be(3);
+ ex.Message.Should().Contain("7");
+ ex.Message.Should().Contain("3");
+ ex.Message.Should().Contain("producto");
+ }
+
+ [Fact]
+ public void Constructor_InheritsFromDomainException()
+ {
+ var ex = new RubroConProductosActivosException(1, 2);
+
+ ex.Should().BeAssignableTo();
+ }
+}