diff --git a/SAS/TMSS/backend/services/scheduling/lib/constraints.py b/SAS/TMSS/backend/services/scheduling/lib/constraints.py
index 4b85778380d8d1ce51919f60c37d79fae9a7eb4d..1956722614b27e21a9583be1e7838fde69c62f99 100644
--- a/SAS/TMSS/backend/services/scheduling/lib/constraints.py
+++ b/SAS/TMSS/backend/services/scheduling/lib/constraints.py
@@ -1000,9 +1000,6 @@ def evaluate_sky_transit_constraint(scheduling_unit: models.SchedulingUnitBluepr
             logger.warning("SUB id=%s task id=%s could not determine pointing to evaluate sky transit constraint", scheduling_unit.id, target_obs_task.id)
             result.score = 0
             return result
-        elif transit_pointings[0].direction_type not in ['J2000', 'MOON', 'SUN']:
-            logger.warning('SUB id=%s task id=%s contains a pointing of unsupported direction_type=%s' % (scheduling_unit.id, target_obs_task.id, transit_pointings[0].direction_type))
-            return result
 
         # since the constraint only applies to the middle of the obs, only consider the proposed_center_time
         # take along the relative_start_time of this task compared to the scheduling unit's start_time
@@ -1013,6 +1010,15 @@ def evaluate_sky_transit_constraint(scheduling_unit: models.SchedulingUnitBluepr
 
         # currently we only check at bounds and center, we probably want to add some more samples in between later on
         for pointing in transit_pointings:
+            if pointing.direction_type not in ['J2000', 'MOON', 'SUN', 'AZELGEO']:
+                logger.warning('SUB id=%s task id=%s contains a pointing of unsupported direction_type=%s' % (scheduling_unit.id, target_obs_task.id, pointing.direction_type))
+                result.score = 0
+                return result
+
+            if pointing.direction_type == 'AZELGEO':
+                logger.warning('ignoring AZELGEO pointing for transit constraint for SUB id=%s task id=%s pointing_target=%s' % (scheduling_unit.id, target_obs_task.id, pointing.target))
+                continue
+
             transits = coordinates_timestamps_and_stations_to_target_transit(pointing=pointing,
                                                                              timestamps=(task_proposed_center_time,),
                                                                              stations=tuple(stations),
@@ -1045,6 +1051,12 @@ def evaluate_sky_transit_constraint(scheduling_unit: models.SchedulingUnitBluepr
                     result.message = "offset of %s[s] at task_center='%s' from transit at '%s' at %s for %s is not within [%s, %s]" % (offset, task_proposed_center_time, transit_timestamp, station, pointing, transit_from_limit, transit_to_limit)
                     logger.debug(result)
 
+    if len(optimal_start_times) == 0:
+        result.earliest_possible_start_time = proposed_start_time
+        result.optimal_start_time = None
+        result.score = 1
+        return result
+
     # compute the overall averaged result
     if len(optimal_start_times) == 1:
         result.optimal_start_time = optimal_start_times[0]
@@ -1094,10 +1106,6 @@ def evaluate_sky_min_elevation_constraint(scheduling_unit: models.SchedulingUnit
         return result
 
     for task in scheduling_unit.observation_tasks.all():
-        if get_target_sap_pointings(task) and get_target_sap_pointings(task)[0].direction_type not in ['J2000', 'MOON', 'SUN']:
-            logger.warning('SUB id=%s task id=%s contains a pointing of unsupported direction_type=%s' % (scheduling_unit.id, task.id, get_target_sap_pointings(task)[0].direction_type))
-            return result
-
         stations = get_stations_to_be_evaluated(task, proposed_start_time, 10e4)
 
         # determine the min_elevation and stations depending on observation type
@@ -1107,16 +1115,32 @@ def evaluate_sky_min_elevation_constraint(scheduling_unit: models.SchedulingUnit
             # target imaging, and beamforming or combined observations all use min_elevation.target
             min_elevation = Angle(constraints['sky']['min_elevation']['target'], unit=astropy.units.rad)
             for pointing in get_target_sap_pointings(task):
-                pointings_and_min_elevations.append((pointing, min_elevation))
+                if pointing.direction_type not in ['J2000', 'MOON', 'SUN', 'AZELGEO']:
+                    logger.warning('SUB id=%s task id=%s contains a pointing of unsupported direction_type=%s for min_elevation' % (scheduling_unit.id, task.id, pointing.direction_type))
+                    result.score = 0
+                    return result
+                if pointing.direction_type == 'AZELGEO':
+                    logger.info('ignoring AZELGEO pointing for min_elevation constraint for SUB id=%s task id=%s pointing_target=%s' % (scheduling_unit.id, task.id, pointing.target))
+                else:
+                    pointings_and_min_elevations.append((pointing, min_elevation))
 
         if task.is_calibrator_observation:
             # calibrator and/or combined observations all use min_elevation.calibrator
             min_elevation = Angle(constraints['sky']['min_elevation']['calibrator'], unit=astropy.units.rad)
             for pointing in get_calibrator_sap_pointings(task):
-                pointings_and_min_elevations.append((pointing, min_elevation))
+                if pointing.direction_type not in ['J2000', 'MOON', 'SUN', 'AZELGEO']:
+                    logger.warning('SUB id=%s task id=%s contains a pointing of unsupported direction_type=%s for min_elevation' % (scheduling_unit.id, task.id, pointing.direction_type))
+                    result.score = 0
+                    return result
+                if pointing.direction_type == 'AZELGEO':
+                    logger.info('ignoring AZELGEO pointing for min_elevation constraint for SUB id=%s task id=%s pointing_target=%s' % (scheduling_unit.id, task.id, pointing.target))
+                else:
+                    pointings_and_min_elevations.append((pointing, min_elevation))
 
         if not pointings_and_min_elevations:
-            logger.warning("SUB id=%s task id=%s could not determine pointing to evaluate sky constraints", scheduling_unit.id, task.id)
+            logger.debug("SUB id=%s task id=%s could not determine pointing to evaluate sky min_elevation constraints", scheduling_unit.id, task.id)
+            result.earliest_possible_start_time = proposed_start_time
+            result.score = 1
             return result
 
         # evaluate at least at the gridded start/stop of observation
@@ -1251,6 +1275,9 @@ def get_timestamps_elevations_and_offset_to_transit(scheduling_unit: models.Sche
     offsets_to_transits = []
     lowest_elevation = 1e99
     for pointing in transit_pointings:
+        if pointing.direction_type == 'AZELGEO':
+            continue
+
         elevation_at_start = compute_elevation(pointing, gridded_start_time, station)
         elevation_at_stop = compute_elevation(pointing, gridded_stop_time, station)
         elevation_at_center = compute_elevation(pointing, gridded_center_time, station)
@@ -1317,6 +1344,10 @@ def evaluate_sky_min_distance_constraint(scheduling_unit: models.SchedulingUnitB
             # currently we only check at bounds and center, we probably want to add some more samples in between later on
             # loop over all bodies and their respective min_distance constraints
             for pointing in sap_pointings:
+                if pointing.direction_type == 'AZELGEO':
+                    logger.debug('ignoring AZELGEO pointing for min_distance constraint for SUB id=%s task id=%s pointing_target=%s' % (scheduling_unit.id, obs_task.id, pointing.target))
+                    continue
+
                 for body, min_distance in constraints.items():
                     for gridded_timestamp in gridded_timestamps:
                         distances = coordinates_and_timestamps_to_separation_from_bodies(pointing=pointing,
@@ -1356,7 +1387,7 @@ def evaluate_sky_min_distance_constraint(scheduling_unit: models.SchedulingUnitB
         # largest possible distance is half a great-circle, so Pi radians. Should yield a score of 0.
         # smallest possible distance is 0. Should yield a score of 1.
         # so just normalize the smallest_actual_distance over Pi
-        result.score = 1.0 - (smallest_actual_distance/3.1415)
+        result.score = (1.0 - (smallest_actual_distance/3.1415)) if smallest_actual_distance < 3.14 else 1
 
         # for min_distance there is no optimal start time.
         # any timestamp meeting the constraint is good enough.
@@ -1990,7 +2021,7 @@ def get_optimal_start_time(scheduling_unit: models.SchedulingUnitBlueprint, lowe
     # seek nearest transit around lower_bound
     result = evaluate_sky_transit_constraint(scheduling_unit, gridder.grid_time(lower_bound), gridder=gridder, which='nearest')
     if not result.is_constraint_met and result.optimal_start_time is None:
-        # could not determine an optimal starttime (maybe no stations are available?)
+        # could not determine an optimal starttime (maybe no stations are available?, or azelgeo pointing?)
         return None
 
     optimal_start_time = result.optimal_start_time
@@ -2005,7 +2036,8 @@ def get_optimal_start_time(scheduling_unit: models.SchedulingUnitBlueprint, lowe
         optimal_start_time = get_earliest_possible_start_time(scheduling_unit, lower_bound, lower_bound+timedelta(hours=24), gridder=gridder)
         logger.debug("get_optimal_start_time SUB id=%s earliest_possible_start_time and optimal_start_time='%s'", scheduling_unit.id, optimal_start_time)
 
-    assert optimal_start_time is not None and optimal_start_time >= lower_bound, "SUB id=%s cannot find optimal start_time > %s" % (scheduling_unit.id, lower_bound)
+    if optimal_start_time is None:
+        return None
 
     optimal_start_time = round_to_second_precision(optimal_start_time)
     logger.debug("get_optimal_start_time SUB id=%s lower_bound='%s' optimal_start_time='%s' (took %.1f[s])", scheduling_unit.id, lower_bound, optimal_start_time, (datetime.utcnow() - _method_start_timestamp).total_seconds())
diff --git a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py
index a17f1dcadb6fd71398d81d46983fb534d70332e6..e732a13e8e0e2be64de393dbffa539423db94725 100644
--- a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py
+++ b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py
@@ -955,7 +955,16 @@ class Scheduler:
                             Angle(lowest_elevation, astropy.units.rad).degree if lowest_elevation else None,
                             '/'.join(str(q) for q in unit.main_observation_task.used_station_counts))
                     except Exception as e:
-                        logger.warning(e)
+                        logger.log(log_level,
+                            "  id=% 4d %s %s %s start_time='%s'[UTC]  dur=%4d[min]  %s name=%s",
+                            unit.id,
+                            ("'%s'" % (unit.project.name[:8],)).ljust(10),
+                            unit.priority_queue.value,
+                            'D' if unit.is_dynamically_scheduled else 'F',
+                            round_to_second_precision(unit.scheduled_observation_start_time),
+                            round(unit.specified_main_observation_duration.total_seconds()/60.0),
+                            unit.status.value.ljust(14),
+                            ("'%s'" % (unit.name[:32],)).ljust(34))
                 logger.log(log_level, "-----------------------------------------------------------------")
                 # TODO: report on schedule density
         except Exception as e:
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/plots.py b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/plots.py
index 15a061036f63b1bdda5595d663b5899cca1401b7..61ac7b8f0e9ba1dfbf936f19d33ab328dfefed01 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/adapters/plots.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/adapters/plots.py
@@ -243,7 +243,12 @@ def scheduling_constraints_plot(scheduling_units: Union[models.SchedulingUnitBlu
 
             # plot an elevation line chart per pointing
             for pointing in pointings:
-                obs_elevations = [compute_elevation(pointing=pointing, timestamp=timestamp, station=station) * 180.0 / 3.1415 for timestamp in obs_timestamps]
+                try:
+                    obs_elevations = [compute_elevation(pointing=pointing, timestamp=timestamp, station=station) * 180.0 / 3.1415 for timestamp in obs_timestamps]
+                except ValueError:
+                    # plot elevation for non-J2000 pointings as 0, so we at least have an entry in the legend.
+                    obs_elevations = [0 for _ in obs_timestamps]
+
                 # simple line plot
                 elevation_axes.plot(obs_timestamps, obs_elevations,
                                     label=pointing.str_astro() + (" Cal" if pointing in cal_pointings else ''),
@@ -291,6 +296,9 @@ def scheduling_constraints_plot(scheduling_units: Union[models.SchedulingUnitBlu
 
                     # for target observation(s) also annotate the transit info (transit timestamp in UTC & LST, and elevation)
                     for p_idx, pointing in enumerate(get_transit_offset_pointings(obs_task)):
+                        if pointing.direction_type == 'AZELGEO':
+                            continue
+
                         transit_timestamp = coordinates_timestamp_and_station_to_target_transit(pointing, obs_center_timestamp, observer, n_grid_points=200)
 
                         # plot the limits within which this transit for this pointing should occur
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py b/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
index 4e5d23476d06cd96299f19175861e5499326e195..59959ec16da6f6908a656b1c17d168ad3ec6b9fe 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
@@ -59,7 +59,7 @@ class Pointing():
 
     def str_astro(self):
         '''represent the pointing in astropy hmsdms, direction_type, targetname'''
-        return "%s%s%s" % (self.as_SkyCoord().to_string('hmsdms'),
+        return "%s%s%s" % ('%.3f°, %.3f°' % (astropy.coordinates.Angle(self.angle1, unit=astropy.units.rad).deg, astropy.coordinates.Angle(self.angle2, unit=astropy.units.rad).deg) if self.direction_type=='AZELGEO' else self.as_SkyCoord().to_string('hmsdms'),
                            '' if self.direction_type=='J2000' else self.direction_type,
                            (" '"+self.target+"'") if self.target else "")