diff --git a/models/vrp.rb b/models/vrp.rb
index b9de6afa9..974154193 100644
--- a/models/vrp.rb
+++ b/models/vrp.rb
@@ -141,6 +141,16 @@ def self.check_consistency(hash)
       hash[:services] ||= []
       hash[:shipments] ||= []
 
+      # shipment relation consistency
+      shipment_relations = hash[:relations]&.select{ |r| r[:type] == :shipment }&.flat_map{ |r| r[:linked_ids] }.to_a
+      unless shipment_relations.size == shipment_relations.uniq.size
+        raise OptimizerWrapper::UnsupportedProblemError.new(
+          'Services can appear in at most one shipment relation. '\
+          'Following services appear in multiple shipment relations',
+          shipment_relations.detect{ |id| shipment_relations.count(id) > 1 }
+        )
+      end
+
       # vehicle time cost consistency
       if hash[:vehicles]&.any?{ |v| v[:cost_waiting_time_multiplier].to_f > (v[:cost_time_multiplier] || 1) }
         raise OptimizerWrapper::DiscordantProblemError, 'cost_waiting_time_multiplier cannot be greater than cost_time_multiplier'
@@ -150,11 +160,9 @@ def self.check_consistency(hash)
       # TODO: Active Hash should be checking this
       [:matrices, :units, :points, :rests, :zones, :timewindows,
        :vehicles, :services, :shipments, :subtours].each{ |key|
-        next if hash[key].to_a.collect{ |v| v[:id] }.uniq!.nil?
+        next if hash[key]&.collect{ |v| v[:id] }&.uniq!.nil?
 
-        raise OptimizerWrapper::DiscordantProblemError.new(
-          "#{key} IDs should be unique"
-        )
+        raise OptimizerWrapper::DiscordantProblemError.new("#{key} IDs should be unique")
       }
 
       # matrix_id consistency
diff --git a/test/models/vrp_consistency_test.rb b/test/models/vrp_consistency_test.rb
index e40588990..9de6a9fdd 100644
--- a/test/models/vrp_consistency_test.rb
+++ b/test/models/vrp_consistency_test.rb
@@ -344,5 +344,20 @@ def test_consistent_schedule
         Models::Vrp.check_consistency(vrp)
       end
     end
+
+    def test_services_cannot_appear_in_more_than_one_shipment_relation
+      vrp = VRP.basic
+      vrp[:relations] = [
+        { type: :shipment, linked_ids: %w[service_1 service_2] },
+        { type: :shipment, linked_ids: %w[service_1 service_3] }
+      ]
+      error = assert_raises OptimizerWrapper::UnsupportedProblemError do
+        Models::Vrp.check_consistency(TestHelper.coerce(vrp))
+      end
+
+      assert_equal 'Services can appear in at most one shipment relation. '\
+                 'Following services appear in multiple shipment relations',
+                   error.message, 'Error message does not match'
+    end
   end
 end
diff --git a/test/models/vrp_test.rb b/test/models/vrp_test.rb
index cb7314158..26d5a04e3 100644
--- a/test/models/vrp_test.rb
+++ b/test/models/vrp_test.rb
@@ -281,7 +281,7 @@ def test_available_interval
     def test_no_lapse_in_relation
       vrp = VRP.basic
       vrp[:relations] = [{
-        type: 'vehicle_group_duration_on_months',
+        type: :vehicle_group_duration_on_months,
         linked_vehicle_ids: ['vehicle_0']
       }]
 
@@ -289,7 +289,7 @@ def test_no_lapse_in_relation
       assert_empty vrp[:relations] # reject relation because lapse is mandatory
 
       vrp[:relations] = [{
-        type: 'vehicle_group_duration_on_months',
+        type: :vehicle_group_duration_on_months,
         linked_vehicle_ids: ['vehicle_0'],
         lapse: 2
       }]
@@ -298,7 +298,7 @@ def test_no_lapse_in_relation
 
       vrp = VRP.lat_lon_two_vehicles
       vrp[:relations] = [{
-        type: 'vehicle_trips',
+        type: :vehicle_trips,
         linked_vehicle_ids: vrp[:vehicles].collect{ |v| v[:id] }
       }]
       Models::Vrp.filter(vrp)