@@ -891,12 +891,11 @@ export class BatchTriggerV3Service extends BaseService {
891891 }
892892
893893 // FIX for Issue #2965: When a run is cached (duplicate idempotencyKey),
894- // we need to create a BatchTaskRunItem and immediately mark it as completed.
895- // This ensures the batch completion check (completedCount === expectedCount) works correctly.
894+ // we need to handle it based on whether the cached run is already complete.
896895 const isAlreadyComplete = isFinalRunStatus ( result . run . status ) ;
897896
898897 logger . debug (
899- "[BatchTriggerV2][processBatchTaskRunItem] Cached run detected, creating batch item " ,
898+ "[BatchTriggerV2][processBatchTaskRunItem] Cached run detected" ,
900899 {
901900 batchId : batch . friendlyId ,
902901 runId : task . runId ,
@@ -907,31 +906,45 @@ export class BatchTriggerV3Service extends BaseService {
907906 }
908907 ) ;
909908
909+ // If the cached run is NOT in a final status (still PENDING or EXECUTING),
910+ // we should NOT create a BatchTaskRunItem because:
911+ // 1. The original item will complete when the run finishes
912+ // 2. Creating a duplicate item would cause the batch to hang forever
913+ // (as noted in Devin AI review)
914+ if ( ! isAlreadyComplete ) {
915+ logger . debug (
916+ "[BatchTriggerV2][processBatchTaskRunItem] Cached run still in progress, skipping batch item creation" ,
917+ {
918+ batchId : batch . friendlyId ,
919+ cachedRunId : result . run . id ,
920+ cachedRunStatus : result . run . status ,
921+ }
922+ ) ;
923+ // Return false to NOT increment expectedCount
924+ return false ;
925+ }
926+
927+ // The cached run is already complete, create a BatchTaskRunItem and increment completedCount
910928 try {
911- // Create a BatchTaskRunItem for the cached run
912929 await this . _prisma . batchTaskRunItem . create ( {
913930 data : {
914931 batchTaskRunId : batch . id ,
915932 taskRunId : result . run . id ,
916- // Mark as COMPLETED if the cached run is already finished
917- status : isAlreadyComplete ? "COMPLETED" : batchTaskRunItemStatusForRunStatus ( result . run . status ) ,
933+ status : "COMPLETED" ,
918934 } ,
919935 } ) ;
920936
921- // If the cached run is already complete, we need to increment completedCount
922- // since this item won't go through the normal completeBatchTaskRunItemV3 flow
923- if ( isAlreadyComplete ) {
924- await this . _prisma . batchTaskRun . update ( {
925- where : { id : batch . id } ,
926- data : {
927- completedCount : {
928- increment : 1 ,
929- } ,
937+ // Increment completedCount since the cached run is already finished
938+ await this . _prisma . batchTaskRun . update ( {
939+ where : { id : batch . id } ,
940+ data : {
941+ completedCount : {
942+ increment : 1 ,
930943 } ,
931- } ) ;
932- }
944+ } ,
945+ } ) ;
933946
934- // Return true so expectedCount is incremented
947+ // Return true so expectedCount is incremented (matches completedCount increment above)
935948 return true ;
936949 } catch ( error ) {
937950 if ( isUniqueConstraintError ( error , [ "batchTaskRunId" , "taskRunId" ] ) ) {
0 commit comments