> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.buildworkforce.ai/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Catch Action Tool

### What is a Catch Action?
A Catch Action is a special type of JavaScript action that only runs when the action directly before it fails with an error. Think of it as a safety net that catches problems and lets you handle them gracefully.
**Why use Catch Actions?**
* Prevent your entire tool from failing when one step goes wrong
* Provide helpful error messages instead of technical jargon
* Implement retry logic or fallback behaviors
* Transform errors into useful information
* Log errors for later troubleshooting
**When to use Catch Actions:**
* After API calls that might fail (network errors, rate limits, etc.)
* After complex JavaScript actions that could have runtime errors
* When calling external services that may be unreliable
* When you want to provide a default value if something fails
* When you need to log or report errors differently

### How Catch Actions Work
**The sequence:**
1. An action executes (API call, JavaScript, etc.)
2. **If the action succeeds** → Continue to the next action, skip the Catch Action
3. **If the action fails** → Run the Catch Action immediately after
4. The Catch Action's output **replaces** the failed action's output
5. Continue with remaining actions
**Example flow:**
```
Action 1: fetchUserData (API call)
Action 2: catchUserError (Catch Action) ← Only runs if Action 1 fails
Action 3: processData (JavaScript) ← Receives output from Action 1 OR Action 2
```
**Scenario A - Success:**
1. Action 1 succeeds → Returns `{ userId: 123, name: "John" }`
2. Action 2 is **skipped**
3. Action 3 receives `{ userId: 123, name: "John" }`
**Scenario B - Failure:**
1. Action 1 fails → Returns `{ error: "Network timeout" }`
2. Action 2 **runs** → Returns `{ userId: null, name: "Unknown", error: "Could not fetch user" }`
3. Action 3 receives `{ userId: null, name: "Unknown", error: "Could not fetch user" }`

![](https://storage.crisp.chat/users/helpdesk/website/-/c/8/1/5/c8154f3e149fd000/image_13gdyf9.png)

### Adding a Catch Action to Your Tool
**Important:** A Catch Action must come **immediately after** the action you want to protect.
1. Add the action you want to protect (e.g., an API call)
2. Click **"Add Action"** directly below it
3. Select **"Catch Action"** as the action type
4. Enter a descriptive **action name** (e.g., `catchApiError`, `handleFetchError`)
5. Write JavaScript code to handle the error
6. Click **"Add"** or **"Save"**

![](https://storage.crisp.chat/users/helpdesk/website/-/c/8/1/5/c8154f3e149fd000/image_ioarb5.png)

**Positioning matters:**
```
✅ Correct:
  Action 1: fetchData
  Action 2: catchFetchError (Catch) ← Directly after Action 1

❌ Incorrect:
  Action 1: fetchData
  Action 2: processData
  Action 3: catchFetchError (Catch) ← Too late! Won't catch Action 1 errors
```

### Writing Catch Action Code
Catch Actions use JavaScript code, just like regular JavaScript actions. You have access to the same `ctx` object, which includes information about the error.

#### Accessing Error Information
When a Catch Action runs, `ctx` contains:
* The error message from the failed action
* All previous successful action outputs
* All tool inputs
* `ctx` when an API call fails:
```
{
  // Your tool inputs
  userId: "12345",

  // Previous successful actions
  validateInput: { valid: true },

  // The failed action's error
  fetchUser: {
    error: "Request failed with status code 404"
  }
}
```

#### Pattern 1: Provide a Default Value
Return a sensible default when something fails:
```
async function main() {
  return {
    userId: ctx.userId,
    name: "Unknown User",
    email: "no-email@example.com",
    status: "error",
    message: "Could not fetch user data. Using default values."
  };
}
```
**Use case:** When later actions need specific fields to exist, provide them with default values.

#### Pattern 2: Log Error and Return Graceful Message
Capture the technical error but return a user-friendly message:
```
async function main() {
  const originalError = ctx.fetchUser?.error || "Unknown error occurred";

  console.log("API call failed:", originalError);

  return {
    success: false,
    message: "We couldn't retrieve the data right now. Please try again later.",
    errorCode: "FETCH_FAILED"
  };
}
```
**Use case:** When you want to hide technical details from end users but still log them for debugging.

#### Pattern 3: Retry Logic
Attempt to recover with alternative data or approach:
```
async function main() {
  // If primary API failed, return instructions to try backup source
  return {
    useFallback: true,
    fallbackSource: "cache",
    message: "Primary source failed, use cached data instead"
  };
}
```
**Note:** Catch Actions can't make API calls directly, but they can return instructions for later actions.

#### Pattern 4: Error Classification
Categorize errors and provide specific guidance:
```
async function main() {
  const error = ctx.fetchData?.error || "";

  let errorType;
  let suggestion;

  if (error.includes("404")) {
    errorType = "NOT_FOUND";
    suggestion = "The requested resource does not exist";
  } else if (error.includes("401") || error.includes("403")) {
    errorType = "UNAUTHORIZED";
    suggestion = "Check your API credentials";
  } else if (error.includes("timeout")) {
    errorType = "TIMEOUT";
    suggestion = "The service took too long to respond. Try again.";
  } else if (error.includes("429")) {
    errorType = "RATE_LIMIT";
    suggestion = "Too many requests. Please wait before retrying.";
  } else {
    errorType = "UNKNOWN";
    suggestion = "An unexpected error occurred";
  }

  return {
    success: false,
    errorType: errorType,
    message: suggestion,
    originalError: error
  };
}
```
**Use case:** When different error types require different handling or user messages.

#### Pattern 5: Partial Recovery
Extract whatever valid data exists before the error:
```
async function main() {
  return {
    success: false,
    partialData: ctx.previousAction?.partialResults || [],
    failedAt: "fetchUser",
    message: "Completed partial processing before error occurred"
  };
}
```
**Use case:** When multi-step processes can preserve some results even if later steps fail.

### Catch Action Examples

#### Example 1: Handling API Errors
**Scenario:** Fetch user data from an API that might return 404 or be down
```
// Action 1: fetchUser (API Action)
// GET https://api.example.com/users/{{userId}}

// Action 2: catchUserError (Catch Action)
async function main() {
  console.log("User fetch failed, providing default user object");

  return {
    responseBody: {
      userId: ctx.userId,
      name: "Unknown User",
      status: "not_found"
    },
    responseStatus: 200, // Fake success status for downstream actions
    wasError: true
  };
}

// Action 3: processUser (JavaScript Action)
// This action will receive either real user data or the default from catchUserError
async function main() {
  const user = ctx.fetchUser.responseBody;

  if (ctx.catchUserError?.wasError) {
    return {
      message: `User ${ctx.userId} not found. Created placeholder.`,
      user: user
    };
  }

  return {
    message: `Successfully processed user ${user.name}`,
    user: user
  };
}
```

#### Example 2: Rate Limit Handling
**Scenario:** API might hit rate limits, need to handle gracefully
```
// Action 1: searchProducts (API Action)

// Action 2: catchRateLimit (Catch Action)
async function main() {
  const error = ctx.searchProducts?.error || "";

  if (error.includes("429") || error.includes("rate limit")) {
    return {
      responseBody: {
        products: [],
        message: "Search rate limit exceeded. Please try again in a few minutes.",
        retryAfter: 60
      },
      responseStatus: 429,
      isRateLimited: true
    };
  }

  // Some other error
  return {
    responseBody: {
      products: [],
      message: "Search failed. Please try again later.",
      error: error
    },
    responseStatus: 500
  };
}
```

#### Example 3: Data Validation Errors
**Scenario:** JavaScript action validates data and might throw errors
```
// Action 1: validateAndProcess (JavaScript Action)
async function main() {
  if (!ctx.email.includes('@')) {
    throw new Error("Invalid email format");
  }

  if (ctx.age < 18) {
    throw new Error("Must be 18 or older");
  }

  return {
    valid: true,
    data: { email: ctx.email, age: ctx.age }
  };
}

// Action 2: catchValidationError (Catch Action)
async function main() {
  const error = ctx.validateAndProcess?.error || "";

  return {
    valid: false,
    errors: [error],
    providedData: {
      email: ctx.email,
      age: ctx.age
    },
    message: "Validation failed: " + error
  };
}

// Action 3: respondToUser (JavaScript Action)
async function main() {
  if (!ctx.validateAndProcess.valid) {
    return {
      status: "error",
      message: ctx.validateAndProcess.message
    };
  }

  return {
    status: "success",
    message: "Data validated successfully"
  };
}
```

#### Example 4: Chaining Multiple Catch Actions
**Scenario:** Multiple risky operations, each needs error handling
```
// Action 1: fetchUser (API Action)
// Action 2: catchUserError (Catch Action)
async function main() {
  return {
    responseBody: { userId: ctx.userId, name: "Default User" },
    responseStatus: 200,
    errorOccurred: true
  };
}

// Action 3: fetchOrders (API Action) - Uses user data
// Action 4: catchOrdersError (Catch Action)
async function main() {
  return {
    responseBody: { orders: [] },
    responseStatus: 200,
    errorOccurred: true,
    message: "Could not fetch orders, returning empty list"
  };
}

// Action 5: formatReport (JavaScript Action)
async function main() {
  const user = ctx.fetchUser.responseBody;
  const orders = ctx.fetchOrders.responseBody.orders;

  const warnings = [];
  if (ctx.catchUserError?.errorOccurred) {
    warnings.push("User data unavailable");
  }
  if (ctx.catchOrdersError?.errorOccurred) {
    warnings.push("Orders data unavailable");
  }

  return {
    report: {
      user: user.name,
      orderCount: orders.length,
      warnings: warnings
    }
  };
}
```

### Testing Catch Actions
Testing Catch Actions is tricky because you need the previous action to fail. Here's how to test them:

#### Method 1: Test in isolation
* Click the **"Test"** button at the bottom of the action editor
* Manually provide an error context:
```
{
  "userId": "123",
  "fetchUser": {
    "error": "Request failed with status code 404"
  }
}
```
1. Click **"Run Test"**
2. Verify the Catch Action returns appropriate error handling

#### Method 2: Test the full tool with bad inputs
1. Use the **"Test Tool"** button
2. Provide inputs you know will cause the previous action to fail
    * Invalid API endpoint
    * Non-existent user ID
    * Invalid data that will fail validation
3. Verify the Catch Action runs and handles the error correctly

#### Method 3: Temporarily break the previous action
1. Temporarily modify the previous action to force an error
    * Change API URL to an invalid endpoint
    * Add code that throws an error: `throw new Error("Test error")`
2. Test the tool
3. Verify the Catch Action runs
4. **Remember to restore the original action!**

### Troubleshooting Catch Actions
**Problem: Catch Action never runs**
* **Cause:** Previous action is not failing, or Catch Action is not positioned correctly
* **Solution:**
    * Verify the Catch Action is **immediately after** the action it should catch
    * Check that the previous action is actually failing (test it separately)
    * Review the action order in your tool
**Problem: Catch Action runs but tool still fails**
* **Cause:** Catch Action itself has an error in its code
* **Solution:**
    * Test the Catch Action code separately
    * Add try/catch within the Catch Action:
```
async function main() {
  try {
    // Your error handling code
  } catch (e) {
    return { error: "Catch action failed: " + e.message };
  }
}
```
**Problem: Can't access error information**
* **Cause:** The error structure might be different than expected
* **Solution:**
* Log the entire context to see what's available:
* `console.log("Full context:", JSON.stringify(ctx, null, 2));`
* Use safe access patterns:
* `const error = ctx.previousAction?.error || "Unknown error";`
**Problem: Later actions receive wrong data**
* **Cause:** Catch Action's output structure doesn't match what later actions expect
* **Solution:**
    * Make the Catch Action return the same structure as the successful action
    * If original action returns `{ responseBody: {...}, responseStatus: 200 }`, your Catch Action should too
**Problem: Too many Catch Actions making code complex**
* **Cause:** Trying to catch every possible error individually
* **Solution:**
    * Only add Catch Actions for operations that commonly fail or are critical
    * Combine error handling logic into fewer, more comprehensive Catch Actions
    * Consider redesigning the tool if error handling becomes overwhelming

### Catch Action Best Practices

**1. Position correctly**
Always place Catch Actions **immediately after** the action they protect:
```
✅ Action 1: apiCall
✅ Action 2: catchApiError
✅ Action 3: processResult

❌ Action 1: apiCall
❌ Action 2: processResult
❌ Action 3: catchApiError ← Too late
```
**2. Return consistent structures**
Match the output structure of the original action:
```
// If original API action returns:
// { responseBody: {...}, responseStatus: 200 }

// Your Catch Action should return:
async function main() {
  return {
    responseBody: { /* default or error data */ },
    responseStatus: 500,
    errorHandled: true
  };
}
```
**3. Log for debugging**
Always log what error occurred:
```
async function main() {
  const error = ctx.previousAction?.error || "Unknown error";
  console.log("Error caught:", error);

  return { /* your error handling */ };
}
```
**4. Provide actionable messages**
Give clear, helpful information:
```
// ❌ Bad
return { error: "It broke" };

// ✅ Good
return {
  success: false,
  message: "Could not fetch user data. The user ID may not exist or the service is temporarily unavailable.",
  suggestion: "Verify the user ID and try again later."
};
```
**5. Don't overuse**
Only add Catch Actions where needed:
* After external API calls that might fail
* After complex JavaScript that might have runtime errors
* After critical operations where graceful degradation is important
* **Not** after every single action
**6. Test both paths**
Always test:
* Success path (Catch Action is skipped)
* Failure path (Catch Action runs)
**7. Document error handling**
Add comments explaining what errors you're handling and why:
```
async function main() {
  // Handle 404 (not found) and 503 (service unavailable) errors
  // by returning a cached default user object

  return {
    responseBody: { /* default user */ },
    source: "cache"
  };
}
```
 