diff --git a/record-and-playback/core/lib/recordandplayback/workers/archive_worker.rb b/record-and-playback/core/lib/recordandplayback/workers/archive_worker.rb
index 3a58c6696fcd409c4433cc72fe72b55f91d5c652..aac40629ec188cd131dc8fc7cd82dcec20793a87 100755
--- a/record-and-playback/core/lib/recordandplayback/workers/archive_worker.rb
+++ b/record-and-playback/core/lib/recordandplayback/workers/archive_worker.rb
@@ -42,9 +42,8 @@ module BigBlueButton
             !File.exist?(@archived_fail)
           )
 
-          if File.exist?(@archived_norecord)
-            @publisher.put_archive_norecord(@meeting_id)
-          end
+          norecord = File.exist?(@archived_norecord)
+          @publisher.put_archive_norecord(@meeting_id) if norecord
 
           @publisher.put_archive_ended(@meeting_id, success: step_succeeded, step_time: step_time)
 
@@ -56,6 +55,8 @@ module BigBlueButton
           end
           @logger.debug("Finished archive worker for #{@full_id}")
 
+          raise WorkerNoRecordHalt, "Meeting #{@full_id} had no recording marks" if norecord
+
           step_succeeded
         end
       end
diff --git a/record-and-playback/core/lib/recordandplayback/workers/base_worker.rb b/record-and-playback/core/lib/recordandplayback/workers/base_worker.rb
index 5d9159afa88a7e1734f43366bf63a9e8a0991cc0..9b6901c1efcb9dfb4ab02d216e1923b195f63416 100644
--- a/record-and-playback/core/lib/recordandplayback/workers/base_worker.rb
+++ b/record-and-playback/core/lib/recordandplayback/workers/base_worker.rb
@@ -25,6 +25,17 @@ require 'resque'
 
 module BigBlueButton
   module Resque
+    # Base class of exceptions specific to the worker/queue system
+    class WorkerError < StandardError; end
+
+    # Exceptions that should prevent the queue system from executing the next job, but which are not actually
+    # errors.
+    class WorkerHalt < WorkerError; end
+
+    # A meeting had recording enabled (record=true) but did not have recording marks and should not be automatically
+    # processed.
+    class WorkerNoRecordHalt < WorkerHalt; end
+
     class BaseWorker
       @queue = 'rap:base'
 
@@ -45,6 +56,9 @@ module BigBlueButton
         raise "Worker #{@step_name} for #{@meeting_id} failed with result #{success}" unless success
 
         schedule_next_step unless @single_step
+      rescue WorkerHalt => e
+        @logger.info(e.message)
+        @logger.info("Ended worker #{@step_name} for #{@meeting_id} with worker halt. Following steps will not be run.")
       rescue StandardError => e
         @logger.error(e.message)
         e.backtrace.each do |traceline|
diff --git a/record-and-playback/core/lib/recordandplayback/workers/sanity_worker.rb b/record-and-playback/core/lib/recordandplayback/workers/sanity_worker.rb
index 16e7e5874c7ed91c9316714b1fc4619df33e05a3..b5cdf533bbd7dc7e371ccea49b25db47c639c148 100755
--- a/record-and-playback/core/lib/recordandplayback/workers/sanity_worker.rb
+++ b/record-and-playback/core/lib/recordandplayback/workers/sanity_worker.rb
@@ -47,10 +47,7 @@ module BigBlueButton
             FileUtils.touch(@sanity_fail)
           end
 
-          # Avoid the regular process flow if it's a norecord meeting
-          process = !File.exist?(@archived_norecord)
-
-          step_succeeded && process
+          step_succeeded
         end
       end
 
@@ -63,7 +60,6 @@ module BigBlueButton
         super(opts)
         @step_name = 'sanity'
         @post_scripts_path = File.join(BigBlueButton.rap_scripts_path, 'post_archive')
-        @archived_norecord = "#{@recording_dir}/status/archived/#{@full_id}.norecord"
         @sanity_fail = "#{@recording_dir}/status/sanity/#{@full_id}.fail"
         @sanity_done = "#{@recording_dir}/status/sanity/#{@full_id}.done"
       end