{"record":{"id":"fa0f06d75987e7e1","repo":"bensheldon/good_job","slug":"all-batches-must-be-new-not-persisted","errorCode":null,"errorMessage":"All batches must be new (not persisted)","messagePattern":"All batches must be new \\(not persisted\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/models/good_job/batch.rb","lineNumber":81,"sourceCode":"\n    # Bulk-enqueue multiple batches with their jobs in minimal DB round-trips.\n    #\n    # Instead of creating batches one-at-a-time (~7 queries per batch), this method\n    # inserts all batch records and jobs in a fixed number of queries:\n    #   1. INSERT all BatchRecords  (insert_all!)\n    #   2. INSERT all Jobs          (insert_all)\n    #   3. NOTIFY per distinct queue/scheduled_at\n    #\n    # @param batch_job_pairs [Array<Array(GoodJob::Batch, Array<ActiveJob::Base>)>]\n    #   Array of [batch, jobs] pairs. Each batch must be new (not yet persisted).\n    # @return [Array<GoodJob::Batch>] The enqueued batches\n    # @raise [ArgumentError] if any batch is already persisted\n    def self.enqueue_all(batch_job_pairs)\n      batch_job_pairs = Array(batch_job_pairs)\n      return [] if batch_job_pairs.empty?\n\n      batch_job_pairs.each do |(batch, _)|\n        raise ArgumentError, \"All batches must be new (not persisted)\" if batch.persisted?\n      end\n\n      Rails.application.executor.wrap do\n        current_time = Time.current\n        adapter = ActiveJob::Base.queue_adapter\n        execute_inline = adapter.respond_to?(:execute_inline?) && adapter.execute_inline?\n\n        # Phase 1: Insert all batch records\n        batch_rows = _build_batch_rows(batch_job_pairs, current_time)\n        BatchRecord.insert_all!(batch_rows) # rubocop:disable Rails/SkipsModelValidations\n        _mark_batches_persisted(batch_job_pairs, batch_rows, current_time)\n\n        # Phase 2: Build and partition jobs by concurrency limits\n        build_result = _build_and_partition_jobs(batch_job_pairs, current_time)\n\n        # Phase 3–6: Insert, claim, and execute inline jobs\n        lock_strategy = Job.effective_lock_strategy\n        tracker_registered = false","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/bensheldon/good_job/blob/5fcde48f8765e69901ffa9c5a06122b19c73875f/app/models/good_job/batch.rb#L63-L99","documentation":"Error \"All batches must be new (not persisted)\" thrown in bensheldon/good_job.","triggerScenarios":"Thrown at app/models/good_job/batch.rb:81 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Only add unpersisted batches; do not save the batch before enqueueing it.","Build the batch with GoodJob::Batch.new instead of create/save."],"exampleFix":"batch = GoodJob::Batch.new\n# enqueue without calling batch.save first","handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5fcde48f8765e69901ffa9c5a06122b19c73875f","analyzedAt":"2026-08-23T14:55:11.399Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}