Skip to main content
When workflows don’t behave as expected, Activepieces provides comprehensive debugging tools to help you identify and fix issues quickly.

Understanding Flow Runs

Every time a workflow executes, it creates a flow run:
// From packages/shared/src/lib/automation/flow-run/flow-run.ts
export type FlowRun = {
  id: string,
  projectId: string,
  flowId: string,
  flowVersionId: string,
  status: FlowRunStatus,
  logsFileId: string | null,
  startTime: string,
  finishTime: string,
  environment: RunEnvironment,  // PRODUCTION or TESTING
  steps: Record<string, StepOutput> | null,  // All step results
  failedStep?: {
    name: string,
    displayName: string,
    message: string
  },
  stepsCount: number
}

Run Status

export enum FlowRunStatus {
  RUNNING = 'RUNNING',      // Currently executing
  SUCCEEDED = 'SUCCEEDED',  // Completed successfully
  FAILED = 'FAILED',        // Failed on a step
  PAUSED = 'PAUSED',        // Waiting for input
  STOPPED = 'STOPPED'       // Manually stopped
}

Running

Flow is currently executing steps.

Succeeded

All steps completed successfully.

Failed

A step failed, execution stopped.

Viewing Flow Runs

1

Access Run History

Navigate to the Runs tab in your flow or project.
2

Filter Runs

Filter by:
  • Status: Failed, Succeeded, Running
  • Flow: Specific workflow
  • Date Range: Time period
// From packages/server/api/src/app/flows/flow-run/flow-run-service.ts
async list(params: {
  projectId: string,
  flowId?: string[],
  status?: FlowRunStatus[],
  cursor?: string,
  limit: number
}): Promise<SeekPage<FlowRun>> {
  // Filter and paginate runs
}
3

Select a Run

Click on any run to view detailed execution information.

Analyzing Step Execution

Step Output Structure

Each step in a run has detailed output:
{
  "trigger": {
    "status": "SUCCEEDED",
    "output": {
      "body": { /* webhook payload */ },
      "headers": { /* request headers */ }
    },
    "input": {},
    "duration": 5  // milliseconds
  },
  "send_email": {
    "status": "SUCCEEDED",
    "output": {
      "messageId": "abc123",
      "response": "Email sent successfully"
    },
    "input": {
      "to": "[email protected]",
      "subject": "Hello",
      "body": "Welcome!"
    },
    "duration": 1250
  },
  "api_call": {
    "status": "FAILED",
    "errorMessage": "Request failed with status 404",
    "input": {
      "url": "https://api.example.com/user/123",
      "method": "GET"
    },
    "duration": 500
  }
}
See exactly what data was passed to the step:
{
  "input": {
    "to": "[email protected]",
    "subject": "Order Confirmation",
    "body": "Thank you for your order #12345"
  }
}
Input values show variable substitutions after evaluation.

Viewing Execution Logs

Detailed logs are available for each run:
// From packages/server/api/src/app/flows/flow-run/logs/flow-run-logs-service.ts
const flowRunLogsService = {
  async getLogs(request: {
    logsFileId: string,
    projectId: string
  }): Promise<ExecutioOutputFile | null> {
    const file = await fileService.getDataOrUndefined({
      fileId: request.logsFileId,
      projectId: request.projectId
    });
    
    if (isNil(file)) return null;
    
    return JSON.parse(file.data.toString('utf-8'));
  }
}

Log Levels

Logs include:
  • Info: General execution information
  • Debug: Detailed variable values
  • Warning: Non-critical issues
  • Error: Failures and exceptions
Logs are stored for the retention period configured in your plan (default: 14 days).

Common Issues and Solutions

Symptoms:
  • Step executed but output is empty or null
  • Subsequent steps can’t access data
Common Causes:
  1. Step succeeded but returned no data
  2. API returned empty response
  3. Data filtering removed all items
Solutions:
  • Check step configuration
  • Verify API endpoint is correct
  • Review filter conditions
  • Add default values: {{ step.data ?? {} }}
Symptoms:
  • Error: “Cannot read property ‘x’ of undefined”
  • Step fails with “Invalid reference”
Common Causes:
  1. Referenced step hasn’t executed yet
  2. Property path is incorrect
  3. Previous step failed (with continueOnFailure)
Solutions:
// Use safe navigation
{{ trigger?.user?.email || '[email protected]' }}

// Check step status first
{{ api_call.status === 'SUCCEEDED' ? api_call.body : {} }}

// Use null coalescing
{{ step.data ?? defaultValue }}
Symptoms:
  • Step fails with timeout error
  • Long-running operations don’t complete
Common Causes:
  1. External API is slow
  2. Large data processing
  3. Network issues
Solutions:
  • Enable retry on failure
  • Optimize data queries
  • Break into smaller chunks
  • Use webhook responses for async operations
Symptoms:
  • 401 or 403 errors
  • “Invalid credentials” messages
Common Causes:
  1. Connection expired or revoked
  2. Insufficient permissions
  3. API key incorrect
Solutions:
  • Refresh connection authentication
  • Verify API permissions
  • Check connection configuration
  • Test connection separately
Symptoms:
  • Type error: “Expected string, got object”
  • JSON parsing errors
Common Causes:
  1. Passing object where string expected
  2. String where array expected
  3. Missing JSON.stringify/parse
Solutions:
// Convert to string
{{ JSON.stringify(trigger.data) }}

// Parse JSON string
{{ JSON.parse(trigger.jsonString) }}

// Extract specific field
{{ trigger.user.id.toString() }}
Symptoms:
  • Loop step shows as succeeded but no iterations
  • Loop output is empty
Common Causes:
  1. Items array is empty
  2. Items reference is incorrect
  3. Loop is skipped
Solutions:
// Check items before loop
Items: {{ trigger.items.length }} items

// Verify array reference
{{ trigger.data.results }}  // not {{ trigger.data }}

// Add default empty array
{{ trigger.items ?? [] }}

Step-by-Step Debugging

1

Identify Failed Step

Look for the first failed step in the run:
{
  "failedStep": {
    "name": "send_http",
    "displayName": "Call API",
    "message": "Request failed with status 404"
  }
}
2

Review Step Input

Check what data was sent to the step:
  • Are variable references correct?
  • Is data in expected format?
  • Are required fields present?
3

Check Error Message

Read the error message carefully:
"errorMessage": "Request failed with status 404: Route not found"
This tells you:
  • Type of error (404 = Not Found)
  • What failed (Route not found)
4

Verify Previous Steps

Check steps before the failed one:
  • Did they execute successfully?
  • Is their output what you expected?
  • Is data being passed correctly?
5

Test in Isolation

Test the failed step independently:
  1. Go to flow builder
  2. Configure step with sample data
  3. Test step alone
  4. Verify it works
6

Fix and Retry

Once you identify the issue:
  1. Update the flow in builder
  2. Publish changes
  3. Retry the failed run
// From packages/web/src/app/builder/run-list/flow-run-card.tsx
const { mutate: retryRun } = useMutation({
  mutationFn: async ({ run, retryStrategy }) => {
    return await flowRunsApi.retry(run.id, {
      projectId,
      strategy: retryStrategy  // ON_LATEST_VERSION or FROM_FAILED_STEP
    });
  }
});

Retry Strategies

// From packages/shared/src/lib/automation/flow-run/flow-run.ts
export enum FlowRetryStrategy {
  ON_LATEST_VERSION = 'ON_LATEST_VERSION',      // Retry with latest flow version
  FROM_FAILED_STEP = 'FROM_FAILED_STEP'         // Resume from failed step
}
Re-run the entire flow with the latest published version:Use when:
  • You fixed the issue in the flow
  • Flow structure changed
  • Need complete re-execution
Behavior:
  • Starts from trigger
  • Uses latest flow version
  • Creates new run with same input

Testing Best Practices

Use realistic test data that matches production:
// Good test data
{
  "user": {
    "id": 123,
    "email": "[email protected]",
    "name": "Test User",
    "active": true
  }
}

// Poor test data
{
  "user": "test"
}
Test with:
  • Empty arrays: []
  • Null values: null
  • Missing fields
  • Very large datasets
  • Special characters in strings
Deliberately cause errors to verify handling:
  • Invalid API keys
  • Wrong URLs
  • Malformed data
  • Network timeouts
Regularly check production runs:
  • Review failure rate
  • Identify patterns
  • Set up error notifications
  • Track performance metrics

Performance Debugging

Identify Slow Steps

Check step duration in run details:
{
  "fetch_data": {
    "duration": 45000,  // 45 seconds - slow!
    "status": "SUCCEEDED"
  },
  "transform_data": {
    "duration": 150,    // 0.15 seconds - fast
    "status": "SUCCEEDED"
  }
}

Optimization Tips

  1. Reduce API Calls: Batch requests when possible
  2. Filter Early: Remove unnecessary data before loops
  3. Parallel Processing: Use multiple flows for independent tasks
  4. Optimize Loops: Process only what’s needed
  5. Cache Results: Store frequently accessed data

Debugging Tools

Console Logging in Code Actions

export const code = async (inputs) => {
  console.log('Input data:', inputs);
  
  try {
    const result = processData(inputs.data);
    console.log('Processed result:', result);
    return result;
  } catch (error) {
    console.error('Processing failed:', error);
    throw error;
  }
};
Console logs appear in the execution logs for the run.

Add Debug Steps

Insert temporary code actions to inspect data:
{
  "name": "debug_data",
  "type": "CODE",
  "settings": {
    "sourceCode": {
      "code": `
export const code = async (inputs) => {
  return {
    stepOutput: inputs.previousStep,
    typeOf: typeof inputs.previousStep,
    keys: Object.keys(inputs.previousStep || {}),
    values: Object.values(inputs.previousStep || {})
  };
};
      `
    },
    "input": {
      "previousStep": "{{ some_step.output }}"
    }
  }
}

Run Environments

export enum RunEnvironment {
  PRODUCTION = 'PRODUCTION',  // Real triggers, production data
  TESTING = 'TESTING'         // Manual tests, sample data
}
Characteristics:
  • Triggered manually
  • Uses sample data
  • Doesn’t affect production
  • Free (doesn’t count toward limits)
Use for:
  • Developing new flows
  • Testing changes
  • Debugging issues
  • Training and demos

Getting Help

If you’re stuck:
  1. Check Documentation: Search for your error message
  2. Community Forum: Ask the community
  3. Support: Contact support with:
    • Flow ID
    • Run ID
    • Error message
    • Steps to reproduce
When sharing debugging info, redact sensitive data like API keys, passwords, or personal information.

Next Steps

Error Handling

Configure proper error handling

Testing

Best practices for testing

Monitoring

Monitor workflow health

Performance

Optimize workflow performance

Build docs developers (and LLMs) love