Skip to main content

Execution Modes

n8n workflows can execute in different modes depending on how they are triggered. Each mode has unique characteristics that affect execution behavior, data flow, and error handling.

Overview of Execution Modes

Execution modes are defined by the WorkflowExecuteMode type:
// From execution-context.ts:33-44
type WorkflowExecuteModeValues = 
  | 'cli'          // Executed via CLI command
  | 'error'        // Error workflow execution
  | 'integrated'   // Embedded execution
  | 'internal'     // Internal system execution
  | 'manual'       // Test execution from UI
  | 'retry'        // Retry after failure
  | 'trigger'      // Triggered automatically
  | 'webhook'      // Webhook request
  | 'evaluation'   // Evaluation/testing mode
  | 'chat';        // Chat interface

Manual Mode

Manual mode is used for testing workflows in the n8n editor.

Characteristics

// Manual execution always starts from a trigger node
const mode: WorkflowExecuteMode = 'manual';

// Workflow must have a manual trigger node
const manualTrigger: INode = {
  name: 'Manual Trigger',
  type: 'n8n-nodes-base.manualTrigger',
  typeVersion: 1,
  position: [250, 300],
  parameters: {}
};
Key Points:
  • Executions are saved only if saveManualExecutions setting is enabled
  • Full execution data is available in the UI
  • Debugging information is more detailed

Use Cases

  • Testing workflow logic before activation
  • Debugging node configurations
  • Validating expressions with sample data
  • Developing new integrations

Trigger Mode

Trigger mode is used when workflows are activated and run automatically.

Characteristics

const mode: WorkflowExecuteMode = 'trigger';

// Trigger nodes run continuously
const triggerResponse = await nodeType.trigger.call(triggerFunctions);

// Response includes cleanup function
interface ITriggerResponse {
  closeFunction?: () => Promise<void>;
  manualTriggerFunction?: () => Promise<void>;
}

Trigger Types

1

Event-Based Triggers

Listen for external events:
// Webhook trigger
const webhook: INode = {
  name: 'Webhook',
  type: 'n8n-nodes-base.webhook',
  parameters: {
    path: 'my-webhook',
    httpMethod: 'POST'
  }
};

// Activated: http://n8n.instance/webhook/my-webhook
Examples:
  • Webhook triggers (HTTP requests)
  • Form triggers (form submissions)
  • Chat triggers (chat messages)
2

Schedule-Based Triggers

Run on a schedule:
// Schedule trigger
const schedule: INode = {
  name: 'Schedule',
  type: 'n8n-nodes-base.scheduleTrigger',
  parameters: {
    rule: {
      interval: [
        {
          field: 'hours',
          hoursInterval: 1
        }
      ]
    }
  }
};

// Runs every hour
Examples:
  • Cron schedules
  • Interval-based execution
  • Time-based triggers
3

Poll-Based Triggers

Check external sources periodically:
// From triggers-and-pollers.ts:92-110
async runPoll(
  workflow: Workflow,
  node: INode,
  pollFunctions: IPollFunctions
): Promise<INodeExecutionData[][] | null> {
  const nodeType = workflow.nodeTypes.getByNameAndVersion(
    node.type,
    node.typeVersion
  );
  
  if (!nodeType.poll) {
    throw new ApplicationError(
      'Node type does not have a poll function defined'
    );
  }
  
  return await nodeType.poll.call(pollFunctions);
}
Examples:
  • RSS feed polling
  • Email inbox polling
  • API endpoint polling

Lifecycle Management

// Active workflows are managed by ActiveWorkflows class
class ActiveWorkflows {
  // Add workflow to active list
  async add(
    workflowId: string,
    workflow: Workflow,
    mode: WorkflowExecuteMode = 'trigger'
  ): Promise<void> {
    // Start triggers and pollers
    const triggerNodes = workflow.getTriggerNodes();
    for (const node of triggerNodes) {
      const triggerResponse = await runTrigger(workflow, node);
      
      // Store cleanup function
      this.triggers[workflowId] = triggerResponse?.closeFunction;
    }
  }
  
  // Remove workflow from active list
  async remove(workflowId: string): Promise<void> {
    // Call cleanup functions
    const closeFunction = this.triggers[workflowId];
    if (closeFunction) {
      await closeFunction();
    }
  }
}

Webhook Mode

Webhook mode handles incoming HTTP requests to webhook endpoints.

Request Handling

const mode: WorkflowExecuteMode = 'webhook';

// Webhook functions have access to HTTP request
interface IWebhookFunctions {
  getRequestObject(): express.Request;
  getResponseObject(): express.Response;
  getBodyData(): IDataObject;
  getHeaderData(): IDataObject;
  getQueryData(): IDataObject;
  getParamsData(): IDataObject;
}

Response Patterns

// Webhook node returns response immediately
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
  const body = this.getBodyData();
  
  return {
    // Response sent to caller
    webhookResponse: {
      status: 200,
      body: { received: true }
    },
    // Data passed to workflow
    workflowData: [
      [{ json: body }]
    ]
  };
}

Webhook Paths

// Webhook URL format:
// Production: https://your-n8n.com/webhook/{path}
// Test: https://your-n8n.com/webhook-test/{path}

const webhookNode: INode = {
  name: 'Webhook',
  type: 'n8n-nodes-base.webhook',
  parameters: {
    path: 'github-events',
    httpMethod: 'POST',
    authentication: 'headerAuth'
  },
  credentials: {
    headerAuth: {
      id: 'header-auth-id',
      name: 'GitHub Webhook Auth'
    }
  }
};

Internal Mode

Internal mode is used for system operations and subworkflows.

Subworkflow Execution

// Execute Workflow node runs subworkflows in internal mode
const executeWorkflow: INode = {
  name: 'Execute Workflow',
  type: 'n8n-nodes-base.executeWorkflow',
  parameters: {
    workflowId: 'subworkflow-id',
    mode: 'integrated'  // Run in same process
  }
};

// Subworkflow executes in 'internal' mode
const subworkflowMode: WorkflowExecuteMode = 'internal';

Execution Context Inheritance

// From execution-context.ts:48-86
interface IExecutionContext {
  version: 1;
  establishedAt: number;
  source: WorkflowExecuteMode;
  triggerNode?: {
    name: string;
    type: string;
  };
  // Parent execution ID for subworkflows
  parentExecutionId?: string;
  // Encrypted credential context
  credentials?: string;
}

// Subworkflow inherits context from parent
const subworkflowContext = establishExecutionContext({
  source: 'internal',
  parentExecutionId: parentExecution.id,
  credentials: parentExecution.context.credentials
});

Error Mode

Error mode runs error workflows when other workflows fail.

Error Workflow Execution

const mode: WorkflowExecuteMode = 'error';

// Error workflow receives error data
const errorData: IExecutionError = {
  execution: {
    id: 'exec-123',
    mode: 'trigger',
    startedAt: new Date(),
    workflowId: 'workflow-456',
    workflowName: 'Data Sync'
  },
  workflow: {
    id: 'workflow-456',
    name: 'Data Sync'
  },
  node: {
    name: 'HTTP Request',
    type: 'n8n-nodes-base.httpRequest',
    parameters: { url: 'https://api.example.com' }
  },
  error: {
    message: 'Request failed with status code 404',
    stack: '...',
    context: { itemIndex: 0 }
  }
};

Error Workflow Pattern

1

Configure Error Workflow

const workflowSettings: IWorkflowSettings = {
  errorWorkflow: 'error-handler-id'
};
2

Add Error Trigger

const errorTrigger: INode = {
  name: 'Error Trigger',
  type: 'n8n-nodes-base.errorTrigger',
  typeVersion: 1,
  position: [250, 300],
  parameters: {}
};
3

Process Error

// Access error details in subsequent nodes
{{
  subject: `Error in ${$json.workflow.name}`,
  body: `
    Node: ${$json.node.name}
    Error: ${$json.error.message}
    Time: ${$json.execution.startedAt}
  `
}}

Retry Mode

Retry mode re-executes failed workflows or nodes.
const mode: WorkflowExecuteMode = 'retry';

// Retry maintains original execution context
const retryExecution = {
  mode: 'retry',
  originalExecutionId: 'exec-123',
  retryOf: 'exec-123',
  // Retry uses same input data as original
  workflowData: originalExecution.data
};

CLI Mode

CLI mode executes workflows via command line.
# Execute workflow via CLI
n8n execute --id workflow-id

# Execute with custom data
n8n execute --id workflow-id --data '{"key": "value"}'
const mode: WorkflowExecuteMode = 'cli';

// CLI executions:
// - Run synchronously
// - Output to stdout/stderr
// - Exit with status code
// - No web UI interaction

Execution Context

Each execution has a context that persists throughout execution:
// From execution-context.ts
export const establishExecutionContext = (
  source: WorkflowExecuteMode,
  triggerNode?: { name: string; type: string },
  parentExecutionId?: string
): IExecutionContext => {
  return {
    version: 1,
    establishedAt: Date.now(),
    source,
    triggerNode,
    parentExecutionId
  };
};

Mode-Specific Behavior

FeatureManualTriggerWebhookInternalError
Save ExecutionOptionalYesYesYesYes
Live UpdatesYesNoNoNoNo
TimeoutYesYesYesNoNo
Pin DataYesNoNoNoNo
Wait NodesYesYesYesYesNo
Static DataR/WR/WR/WR/WRead
CredentialsAllActiveActiveAllAll

Best Practices

  1. Test in manual mode: Always test workflows before activation
  2. Handle webhook timeouts: Return quick responses, process async
  3. Use appropriate triggers: Match trigger type to use case
  4. Configure error workflows: Set up centralized error handling
  5. Monitor active workflows: Track webhook calls and schedule runs
  6. Cleanup resources: Ensure trigger nodes cleanup properly
  7. Consider execution limits: Be aware of timeout settings
Mode Detection in Nodes:
// Access execution mode in expressions
{{$execution.mode}}

// Conditional logic based on mode
{{
  $execution.mode === 'manual' 
    ? 'Test data' 
    : 'Production data'
}}

Next Steps

Creating Workflows

Learn workflow structure and design

Error Handling

Master error handling patterns