diff --git a/SAS/TMSS/backend/services/scheduling/lib/constraints.py b/SAS/TMSS/backend/services/scheduling/lib/constraints.py
index 16425e050a4978669598e860297e2d0ffaad55ae..32e21905e54b7c239a14006147f57fa26294c4fb 100644
--- a/SAS/TMSS/backend/services/scheduling/lib/constraints.py
+++ b/SAS/TMSS/backend/services/scheduling/lib/constraints.py
@@ -28,7 +28,7 @@ These main methods are used in the dynamic_scheduler to pick the next best sched
 
 from datetime import datetime, timedelta
 from dateutil import parser
-from typing import Callable, Union
+from typing import Callable, Union, Tuple
 from astropy.coordinates import Angle
 from astropy.coordinates.earth import EarthLocation
 import astropy.units
@@ -1699,6 +1699,16 @@ def can_run_without_used_stations(scheduling_unit: models.SchedulingUnitBlueprin
 
     return True
 
+
+def get_blocking_scheduled_units(scheduling_unit: models.SchedulingUnitBlueprint) -> Tuple[models.SchedulingUnitBlueprint]:
+    '''Get a list (tuple) of scheduled scheduling_units overlapping with the scheduled_start/stop_time of the given scheduling_unit'''
+    from .dynamic_scheduling import DEFAULT_INTER_OBSERVATION_GAP
+    scheduled_units = models.SchedulingUnitBlueprint.objects.filter(status__value=models.SchedulingUnitStatus.Choices.SCHEDULED.value)
+    scheduled_units = scheduled_units.filter(scheduled_stop_time__gt=scheduling_unit.scheduled_start_time - DEFAULT_INTER_OBSERVATION_GAP)
+    scheduled_units = scheduled_units.filter(scheduled_start_time__lte=scheduling_unit.scheduled_start_time + scheduling_unit.specified_main_observation_duration + DEFAULT_INTER_OBSERVATION_GAP)
+    return tuple(scheduled_units.all())
+
+
 def determine_unschedulable_reason_and_mark_unschedulable_if_needed(scheduling_unit: models.SchedulingUnitBlueprint, lower_bound: datetime, upper_bound: datetime, gridder: Gridder=None, raise_if_interruped: Callable=noop) -> models.SchedulingUnitBlueprint:
     try:
         logger.debug("determine_unschedulable_reason_and_mark_unschedulable_if_needed: scheduling_unit id=%s", scheduling_unit.id)
@@ -1707,6 +1717,15 @@ def determine_unschedulable_reason_and_mark_unschedulable_if_needed(scheduling_u
             msg = "Stations %s are reserved" % (','.join([str(s) for s in missing_stations]), )
             return mark_independent_subtasks_in_scheduling_unit_blueprint_as_unschedulable(scheduling_unit, msg)
 
+        blocking_units = get_blocking_scheduled_units(scheduling_unit)
+        if blocking_units:
+            if len(blocking_units) == 1:
+                msg = "Scheduling unit id=%s is blocking this unit from being scheduled" % (blocking_units[0].id, )
+                return mark_independent_subtasks_in_scheduling_unit_blueprint_as_unschedulable(scheduling_unit, msg)
+            else:
+                msg = "Scheduling units id=%s is blocking this unit from being scheduled" % (','.join(s.id for s in blocking_units), )
+                return mark_independent_subtasks_in_scheduling_unit_blueprint_as_unschedulable(scheduling_unit, msg)
+
         if not can_run_without_used_stations(scheduling_unit):
             missing_stations = get_missing_stations_for_scheduling_unit(scheduling_unit)
             msg = "Stations %s are already used" % (','.join([str(s) for s in missing_stations]), )
diff --git a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
index a2459ec817cb95069fde2655f35b498d4a83dd78..87654f8079acd74962556192c8f812023d199dd7 100755
--- a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
+++ b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
@@ -407,6 +407,58 @@ class TestFixedTimeScheduling(BaseDynamicSchedulingTestCase):
         # even though it's unschedulable, it should still be positioned at the requested 'at' time (in the past)
         self.assertEqual(at, scheduling_unit_blueprint.scheduled_start_time)
 
+    def test_bug_fix_TMSS_2296_a_fixed_time_unit_blocked_by_another_should_become_unschedulable(self):
+        """
+        Test to reproduce the reported bug that a fixed_time unit is not made unschedulable when blocked by another.
+        See: https://support.astron.nl/jira/browse/TMSS-2296
+        """
+        at = round_to_second_precision(datetime.utcnow() + timedelta(days=1))
+        scheduling_unit_draft = self.create_simple_observation_scheduling_unit_fixed_time(at=at)
+        scheduling_unit_blueprint = create_scheduling_unit_blueprint_and_tasks_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft)
+        scheduling_unit_blueprint.rank = models.SchedulingUnitRank.HIGHEST.value
+        scheduling_unit_blueprint.save()
+
+        # assert blueprint has correct constraints, and is schedulable
+        self.assertEqual('fixed_time', scheduling_unit_blueprint.scheduling_constraints_doc['scheduler'])
+        self.assertEqual(at.isoformat(), scheduling_unit_blueprint.scheduling_constraints_doc['time']['at'])
+        self.assertEqual(scheduling_unit_blueprint.status.value, models.SchedulingUnitStatus.Choices.SCHEDULABLE.value)
+
+        self.scheduler.schedule_fixed_time_scheduling_units()
+
+        # Assert the scheduling_unit has been scheduled
+        scheduling_unit_blueprint.refresh_from_db()
+        self.assertEqual(models.SchedulingUnitStatus.Choices.SCHEDULED.value, scheduling_unit_blueprint.status.value)
+        self.assertEqual(at, scheduling_unit_blueprint.scheduled_start_time)
+
+        # create a second unit, at the same time and try to schedule it.
+        # that should not be possible, and the unit should become unschedulable.
+        scheduling_unit_draft2 = self.create_simple_observation_scheduling_unit_fixed_time(at=at)
+        scheduling_unit_blueprint2 = create_scheduling_unit_blueprint_and_tasks_and_subtasks_from_scheduling_unit_draft(scheduling_unit_draft2)
+        scheduling_unit_blueprint2.rank = models.SchedulingUnitRank.LOWEST.value
+        scheduling_unit_blueprint2.save()
+
+        # assert blueprint has correct constraints, and is schedulable initially...
+        self.assertEqual('fixed_time', scheduling_unit_blueprint2.scheduling_constraints_doc['scheduler'])
+        self.assertEqual(at.isoformat(), scheduling_unit_blueprint2.scheduling_constraints_doc['time']['at'])
+        self.assertEqual(scheduling_unit_blueprint2.status.value, models.SchedulingUnitStatus.Choices.SCHEDULABLE.value)
+
+        # try to schedule the second unit...
+        self.scheduler.schedule_fixed_time_scheduling_units()
+
+        # Assert the scheduling_unit has been NOT scheduled (but is unschedulable)
+        scheduling_unit_blueprint2.refresh_from_db()
+        self.assertEqual(models.SchedulingUnitStatus.Choices.UNSCHEDULABLE.value, scheduling_unit_blueprint2.status.value)
+        expected_msg = "Scheduling unit id=%s is blocking this unit from being scheduled" % (scheduling_unit_blueprint.id,)
+        self.assertEqual(expected_msg, scheduling_unit_blueprint2.unschedulable_reason)
+        self.assertEqual(at, scheduling_unit_blueprint2.scheduled_start_time)
+
+        # Assert the original scheduling_unit is still scheduled
+        scheduling_unit_blueprint.refresh_from_db()
+        self.assertEqual(models.SchedulingUnitStatus.Choices.SCHEDULED.value, scheduling_unit_blueprint.status.value)
+        self.assertEqual(at, scheduling_unit_blueprint.scheduled_start_time)
+
+
+
 
     def test_excetion_during_scheduling_sets_state_to_unschedulable(self):
         """