n8n 2.31.5 → 2.31.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -78,6 +78,7 @@ export declare class InstanceAiService {
78
78
  private readonly threadPushRef;
79
79
  private readonly planRequestsByThread;
80
80
  private readonly schedulerLocks;
81
+ private readonly failedInternalFollowUpStreaks;
81
82
  private readonly pendingCheckpointReentries;
82
83
  private readonly terminalOutcome;
83
84
  private readonly liveness;
@@ -197,6 +198,7 @@ export declare class InstanceAiService {
197
198
  private claimWorkItemSetupRouting;
198
199
  private markWorkItemSetupRouted;
199
200
  private releaseWorkItemSetupRoutingClaim;
201
+ private updateInternalFollowUpFailureStreak;
200
202
  private startInternalFollowUpRun;
201
203
  private schedulePlannedTasks;
202
204
  private createPlannedTaskActionRunner;
@@ -195,6 +195,7 @@ function getAbortReason(signal) {
195
195
  return typeof reason === 'string' ? reason : 'user_cancelled';
196
196
  }
197
197
  const MAX_CONCURRENT_BACKGROUND_TASKS_PER_THREAD = 5;
198
+ const MAX_CONSECUTIVE_FAILED_INTERNAL_FOLLOW_UPS = 3;
198
199
  const TITLE_REFINE_HISTORY_LIMIT = 50;
199
200
  function toConfirmationData(request) {
200
201
  switch (request.kind) {
@@ -273,6 +274,7 @@ let InstanceAiService = class InstanceAiService {
273
274
  this.threadPushRef = new Map();
274
275
  this.planRequestsByThread = new Map();
275
276
  this.schedulerLocks = new Map();
277
+ this.failedInternalFollowUpStreaks = new Map();
276
278
  this.pendingCheckpointReentries = new Map();
277
279
  this.runDebugBuffer = new instance_ai_1.RunDebugBuffer();
278
280
  this.checkpointPruningStopped = true;
@@ -844,6 +846,7 @@ let InstanceAiService = class InstanceAiService {
844
846
  metadata: { completion_source: 'service_cleanup' },
845
847
  });
846
848
  this.schedulerLocks.delete(threadId);
849
+ this.failedInternalFollowUpStreaks.delete(threadId);
847
850
  this.domainAccessTrackersByThread.delete(threadId);
848
851
  this.evalCredentialAllowlists.clearThread(threadId);
849
852
  this.threadPushRef.delete(threadId);
@@ -1686,11 +1689,29 @@ let InstanceAiService = class InstanceAiService {
1686
1689
  async releaseWorkItemSetupRoutingClaim(threadId, workItemId, claimId) {
1687
1690
  await new instance_ai_1.WorkflowLoopStorage(this.agentMemory).releaseSetupRoutingClaim(threadId, workItemId, claimId);
1688
1691
  }
1692
+ updateInternalFollowUpFailureStreak(threadId, status, isInternalFollowUp) {
1693
+ if (status === 'completed' || status === 'suspended') {
1694
+ this.failedInternalFollowUpStreaks.delete(threadId);
1695
+ return;
1696
+ }
1697
+ if (status === 'error' && isInternalFollowUp) {
1698
+ this.failedInternalFollowUpStreaks.set(threadId, (this.failedInternalFollowUpStreaks.get(threadId) ?? 0) + 1);
1699
+ }
1700
+ }
1689
1701
  async startInternalFollowUpRun(user, threadId, message, messageGroupId, isReplanFollowUp = false, checkpoint, resumeReasonOverride, plannedBuild) {
1690
1702
  if (this.runState.hasLiveRun(threadId)) {
1691
1703
  this.logger.warn('Skipping internal follow-up: active run exists', { threadId });
1692
1704
  return '';
1693
1705
  }
1706
+ const failedStreak = this.failedInternalFollowUpStreaks.get(threadId) ?? 0;
1707
+ if (failedStreak >= MAX_CONSECUTIVE_FAILED_INTERNAL_FOLLOW_UPS) {
1708
+ this.logger.warn('Skipping internal follow-up: consecutive follow-up runs keep failing', {
1709
+ threadId,
1710
+ failedStreak,
1711
+ resumeReason: resumeReasonOverride,
1712
+ });
1713
+ return '';
1714
+ }
1694
1715
  const { runId, abortController } = this.runState.startRun({
1695
1716
  threadId,
1696
1717
  user,
@@ -2410,6 +2431,7 @@ let InstanceAiService = class InstanceAiService {
2410
2431
  this.liveness.consumeRunTimeout(runId);
2411
2432
  }
2412
2433
  }
2434
+ this.updateInternalFollowUpFailureStreak(threadId, messageTraceFinalization?.status, resumeReason !== undefined);
2413
2435
  if (!this.runState.hasSuspendedRun(threadId)) {
2414
2436
  if (checkpoint?.isCheckpointFollowUp) {
2415
2437
  await this.finalizeCheckpointFollowUp(user, threadId, checkpoint.checkpointTaskId);
@@ -3143,6 +3165,7 @@ let InstanceAiService = class InstanceAiService {
3143
3165
  this.liveness.consumeRunTimeout(opts.runId);
3144
3166
  }
3145
3167
  }
3168
+ this.updateInternalFollowUpFailureStreak(opts.threadId, messageTraceFinalization?.status, false);
3146
3169
  if (!this.runState.hasSuspendedRun(opts.threadId)) {
3147
3170
  if (opts.checkpoint?.isCheckpointFollowUp) {
3148
3171
  await this.finalizeCheckpointFollowUp(opts.user, opts.threadId, opts.checkpoint.checkpointTaskId);