Automations fail. APIs go down, rate limits hit, data is malformed. The difference between a fragile workflow and a resilient one is how it handles failure. This guide covers every error-handling pattern used across the 56 recipes in this collection.
How it works: Zapier automatically retries failed actions up to 3 times with exponential backoff.
When to rely on it: Transient errors — API timeouts, 500 errors, temporary rate limits.
When it's not enough: Persistent auth failures (401), invalid data (400), or resource-not-found (404). These will fail on every retry.
Recipes using this: crm-001, email-001, pm-002
How it works: A Filter step before a risky action checks whether the action will succeed. If conditions aren't met, the Zap stops gracefully.
Trigger → Filter (does the record exist?) → Action
When to use: When the trigger can fire for both valid and invalid cases. For example, email replies from both prospects and non-prospects.
Example from the collection:
Key rule: Filters should check for the most likely failure point in the next action.
How it works: Each branch of a Paths step is independent. If one path fails, the others still execute.
Trigger → Path A (Slack notification) → FAIL
→ Path B (Email notification) → SUCCESS
→ Path C (CRM update) → SUCCESS
When to use: When you have multiple notification channels and at least one should always succeed.
Recipes using this: crm-007, crm-003, inv-003
Tip: Put the most reliable action (Google Sheets logging) in its own path so it always runs.
How it works: Before sending a notification or creating a record, make a GET request to check the current state of the resource. Only proceed if the state is as expected.
Trigger → Delay → GET /status → Filter (still relevant?) → Action
When to use: After a delay step, when the triggering condition may have been resolved during the wait.
Recipes using this:
Key rule: Never send time-sensitive notifications after a delay without re-checking the trigger condition.
How it works: Write the same data to two independent systems. If one fails, the other still has the record.
Trigger → CRM Update (may fail)
→ Spreadsheet Log (usually reliable)
When to use: When data loss is unacceptable — financial records, attribution data, audit logs.
Recipes using this: crm-012, inv-002, inv-008
Tip: Google Sheets rarely fails and serves as an excellent backup for critical data.
How it works: If an action returns empty or null data, use a default value instead of failing.
field_mapping: {
"company": "{{steps.2.company || 'Unknown'}}",
"hours_spent": "{{steps.1.custom_fields.hours || 1}}"
}
When to use: When missing data shouldn't stop the workflow — the fallback value is acceptable.
Recipes using this:
Key rule: Choose defaults that are safe (won't cause downstream problems) and obvious (clearly flag that data is missing).
How it works: Use "Create or Update" actions instead of "Create" to prevent duplicates. Running the same Zap twice on the same data produces the same result.
Trigger → Create or Update Contact (email as key)
When to use: Any time a trigger might fire multiple times for the same event (webhook retries, polling duplicates).
Recipes using this: crm-001, email-001, sync-001, sync-002
Key rule: Always use "Create or Update" with a unique key (email, order_id, SKU) rather than "Create" alone.
How it works: When the primary action fails, the error is logged to a dedicated "dead letter" spreadsheet or channel for manual follow-up.
Trigger → Primary Action → FAIL → Log to Dead Letter Sheet + Alert Slack
When to use: When some failures need human intervention (e.g., unmatched records, invalid data).
Implementation: In Zapier, set up "Error notifications" in your Zap settings. For custom dead-letter logging, create a second Zap triggered by the first Zap's error webhook.
| HTTP Code | Meaning | Recommended Action |
|---|---|---|
| 200-299 | Success | No action needed |
| 400 | Bad Request | Check field formats — dates, emails, required fields |
| 401 | Unauthorized | Reconnect the app in Zapier (token expired) |
| 403 | Forbidden | Check permissions — does your API key have the right scopes? |
| 404 | Not Found | The resource (contact, task, invoice) doesn't exist. Add a lookup step first |
| 409 | Conflict | Record being modified by another process. Auto-retry usually resolves it |
| 422 | Unprocessable | Data is syntactically valid but semantically wrong (e.g., email already exists) |
| 429 | Too Many Requests | Rate limit hit. Add a Delay step or reduce frequency |
| 500 | Server Error | The app's API is having issues. Auto-retry handles this |
| 502/503 | Service Unavailable | Temporary outage. Auto-retry handles this |
| App | Typical Rate Limit | Recommended Zapier Frequency |
|---|---|---|
| HubSpot (free) | 100 requests/10 sec | No more than 5 Zaps polling HubSpot |
| HubSpot (paid) | 150 requests/10 sec | Comfortable for most setups |
| Mailchimp | 10 concurrent connections | Avoid parallel Zaps hitting Mailchimp |
| Stripe | 100 read, 100 write/sec | Rarely an issue |
| Gmail | 500 emails/day (personal), 2000/day (Workspace) | Use transactional email for high volume |
| Google Sheets | 300 requests/min per project | May hit limits with 50+ Zaps writing to Sheets |
| Slack | 1 message/sec per channel | Space out batch notifications |
For high-volume triggers, use Digest by Zapier to collect events over a time window and process them in a single batch:
High-frequency trigger → Digest (collect for 15 min) → Single batch action
This converts 100 individual API calls into 1, dramatically reducing rate limit pressure.
1. Zap History: Shows every task run, including errors (Dashboard → Zap History)
2. Error Notifications: Configure email alerts for Zap failures (Zap Settings → Notifications)
3. Usage Dashboard: Monitor your monthly task usage (Settings → Usage)
For critical workflows, add monitoring steps:
1. Success logging: Add a Google Sheets row at the end of every Zap with a timestamp and run ID
2. Failure alerting: Configure error notification webhooks to post to a #zap-errors Slack channel
3. Weekly audit: Schedule a Zap that checks the error log sheet and sends a summary email
When an error occurs, escalate based on severity:
| Severity | Definition | Response Time | Notification |
|---|---|---|---|
| Low | Non-critical sync delay (sheet not updated) | Next business day | Zap History review |
| Medium | Customer-facing action missed (confirmation email not sent) | 4 hours | Slack #ops channel |
| High | Financial action failed (invoice not created, payment not logged) | 1 hour | Slack + Email to finance |
| Critical | Data loss risk (backup sync failed, dead-letter queue growing) | Immediate | Phone/PagerDuty |
Part of No-Code Builder Pro
When connecting different apps in Zapier, the biggest challenge is mapping fields correctly between systems that use different names, formats, and types for the same data. This reference covers the most common field transformations you'll encounter.
The same person data is named differently in every app:
| Concept | HubSpot CRM | Salesforce | Mailchimp | Pipedrive | Google Sheets |
|---|---|---|---|---|---|
email | Email | email_address | email[0].value | Column name | |
| First name | firstname | FirstName | FNAME (merge field) | first_name | Column name |
| Last name | lastname | LastName | LNAME (merge field) | last_name | Column name |
| Company | company | Company | COMPANY (merge field) | org_name | Column name |
| Phone | phone | Phone | PHONE (merge field) | phone[0].value | Column name |
| Lead source | leadsource | LeadSource | tag | source | Column name |
| Created date | createdate | CreatedDate | timestamp_signup | add_time | Column name |
| Concept | HubSpot | Salesforce | Pipedrive | Close.io |
|---|---|---|---|---|
| Deal name | dealname | Name | title | lead_name |
| Amount | amount | Amount | value | value |
| Stage | dealstage | StageName | stage_id | status_id |
| Close date | closedate | CloseDate | expected_close_date | date_won |
| Owner | hubspot_owner_id | OwnerId | user_id | user_id |
| Pipeline | pipeline | ForecastCategoryName | pipeline_id | (single pipeline) |
Different apps return dates in different formats. Use Formatter by Zapier to convert:
| Source Format | Example | Convert To | Formatter Action |
|---|---|---|---|
| ISO 8601 | 2025-04-10T14:30:00Z | April 10, 2025 | Date: Format → MMMM D, YYYY |
| ISO 8601 | 2025-04-10T14:30:00Z | 04/10/2025 | Date: Format → MM/DD/YYYY |
| Unix timestamp | 1712758200 | 2025-04-10 | Date: Format → YYYY-MM-DD |
| US format | 04/10/2025 | 2025-04-10 | Date: Format → YYYY-MM-DD |
| Relative | 3 days from now | 2025-04-13 | Date: Add/Subtract → +3 days |
Zapier's date arithmetic: Use the Formatter "Date: Add/Subtract" action for relative dates. Common uses:
{{trigger_date + 14 days}}{{completed_date + 3 days}}{{created_date + 365 days}}| Issue | Example | Fix |
|---|---|---|
| Cents vs. dollars | Stripe returns 4900 (cents) | Divide by 100: {{amount / 100}} using Formatter Math |
| String to number | Form returns "5,000" | Formatter: Number → Remove commas, parse as number |
| Number to currency | 4900 → $49.00 | Formatter: Number → Format as currency |
| Percentage | 0.85 → 85% | Multiply by 100, append % |
Apps represent true/false and status differently:
| App A says | App B wants | How to map |
|---|---|---|
true | "Yes" | Formatter: Text → Lookup Table |
1 | true | Formatter: Number → Boolean |
"active" | true | Filter: Text equals "active" |
"closedwon" | "Won" | Formatter: Text → Lookup Table |
Lookup Table pattern: Use Formatter's "Lookup Table" to translate between systems:
Input → Output
"closedwon" → "Won"
"closedlost" → "Lost"
"proposal" → "Proposal Sent"
"negotiation"→ "In Negotiation"
Many forms collect a full name, but CRMs want first and last separately.
Using Formatter by Zapier:
1. Add Formatter → Text → Split
2. Input: {{full_name}}
3. Separator: (space)
4. Segment: First → first_name, Last → last_name
Edge cases:
Used in contact enrichment and routing workflows.
Using Formatter by Zapier:
1. Formatter → Text → Split
2. Input: {{email}}
3. Separator: @
4. Segment: Last → domain
Result: user@example.com → example.com
Converting text to URL-safe or tag-friendly format.
Using Formatter by Zapier:
1. Formatter → Text → Convert to Lowercase
2. Formatter → Text → Replace → spaces with hyphens
3. Formatter → Text → Replace → remove special characters
Result: "Product Launch 2025!" → "product-launch-2025"
Several email recipes need to construct HTML from structured data.
Using Code by Zapier (JavaScript):
// Input: items array from trigger
const items = inputData.items;
let html = '<table><tr><th>Item</th><th>Qty</th><th>Price</th></tr>';
items.forEach(item => {
html += `<tr><td>${item.name}</td><td>${item.qty}</td><td>$${item.price}</td></tr>`;
});
html += '</table>';
output = [{html: html}];Sometimes you need "if field A exists, use it; otherwise use field B."
Zapier's fallback syntax:
{{steps.1.mobile_phone || steps.1.work_phone || steps.1.home_phone || "No phone"}}
This tries each field in order and uses the first non-empty value.
lifecyclestage, not LifecycleStage"tag1;tag2;tag3"FNAME, LNAME, PHONE. Custom merge fields are also uppercase"subscribed", "unsubscribed", "pending", "cleaned"4900. Always divide by 100 for display"general", not "#general"<@U1234567890> format, not @username*bold*, _italic_, ` code `"1234567890"YYYY-MM-DD (no time component for due dates)These template-like expressions appear in recipe field mappings. Here's how to implement each in Zapier:
| Recipe Syntax | Zapier Implementation | ||
|---|---|---|---|
{{steps.1.field}} | Click + in field, select "Step 1" → field | ||
{{steps.1.amount / 100}} | Add Formatter → Number → Math → Divide by 100 | ||
| `{{value \ | split(' ') \ | first}}` | Add Formatter → Text → Split → First segment |
| `{{value \ | date: '%B %d'}}` | Add Formatter → Date → Format → MMMM DD | |
| `{{value \ | truncate: 200}}` | Add Formatter → Text → Truncate → 200 chars | |
| `{{value \ | upcase}}` | Add Formatter → Text → Convert to Uppercase | |
| `{{value \ | slugify}}` | Add Formatter → Text → Convert to Lowercase + Replace spaces | |
{{current_date}} | Use the Zapier built-in "Zap Trigger Date" field | ||
{{current_date + 14 days}} | Add Formatter → Date → Add → 14 Days | ||
| `{{value_a \ | \ | value_b}}` | Zapier handles this natively — the field falls back to next non-empty value |
Part of No-Code Builder Pro
Get the full Zapier Automation Recipes and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.