AutomationFlowsEmail & Gmail › Catch Failed Invoice Extractions with Easybits, Slack, and Google Drive

Catch Failed Invoice Extractions with Easybits, Slack, and Google Drive

ByFelix @easybits on n8n.io

Monitors incoming invoice emails and catches extraction failures before they slip through. When easybits Extractor can't extract the invoice number from an attachment, the workflow sends a Slack alert to finance so nothing gets lost. Successfully extracted invoices are archived…

Event trigger★★★☆☆ complexity13 nodes@Easybits/N8N Nodes ExtractorSlackGoogle DriveGmail Trigger
Email & Gmail Trigger: Event Nodes: 13 Complexity: ★★★☆☆ Added:

This workflow corresponds to n8n.io template #15098 — we link there as the canonical source.

This workflow follows the Gmail Trigger → Google Drive recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "easybits Extractor Error Handling Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "ea5f0e2c-b460-40de-abca-807b6ee6f3fa",
      "name": "easybits: Extract Invoice Number",
      "type": "@easybits/n8n-nodes-extractor.easybitsExtractor",
      "position": [
        304,
        0
      ],
      "parameters": {},
      "typeVersion": 2
    },
    {
      "id": "900717de-5210-4e2a-8351-9096c9d13e34",
      "name": "Validate: Invoice Number Present",
      "type": "n8n-nodes-base.if",
      "position": [
        688,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "b7761fcc-381a-4d02-baff-21528a6678cc",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.invoice_number }}",
              "rightValue": "null"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "cbe4c2c4-42f9-4b2b-a548-e04547bd29ea",
      "name": "Slack: Notify \u2013 Extraction Failed",
      "type": "n8n-nodes-base.slack",
      "position": [
        1072,
        -16
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f Extraction failed\nAttachment {{ $('Gmail Trigger: New Invoice').item.json.headers.from }}\nEmail {{ $('Gmail Trigger: New Invoice').item.json.headers.subject }}\n\nInvoice number could not be extracted \u2014 needs manual review.\n\nTimestamp: {{ $now.toISO() }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_USER_OR_CHANNEL_ID",
          "cachedResultName": "YOUR_SLACK_USER_OR_CHANNEL"
        },
        "select": "user",
        "otherOptions": {}
      },
      "typeVersion": 2.4
    },
    {
      "id": "74fc37a2-6918-429d-84a9-e3fade3f3408",
      "name": "Upload to Invoice Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1376,
        448
      ],
      "parameters": {
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER_NAME"
        },
        "inputDataFieldName": "attachment_0"
      },
      "typeVersion": 3
    },
    {
      "id": "6bf13dcd-761e-416a-988c-7e3edf704b0f",
      "name": "Gmail Trigger: New Invoice",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "simple": false,
        "filters": {},
        "options": {
          "downloadAttachments": true
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "f5c4b252-32f7-463a-95e1-861f9db2803a",
      "name": "Merge: Extracted Data + File",
      "type": "n8n-nodes-base.merge",
      "position": [
        1072,
        448
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "89d26759-d4b9-4235-b98f-971dad60897f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 400,
        "content": "## \ud83d\udce7 Gmail Trigger\nPolls Gmail every minute for new emails with attachments. Downloads the attachment as binary (`attachment_0`) and passes it downstream together with the email metadata (sender, subject) which is reused in the Slack alert."
      },
      "typeVersion": 1
    },
    {
      "id": "3c535596-9225-48bf-b035-23712532e1b8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 400,
        "content": "## \ud83e\udd16 Invoice Extraction\nSends the email attachment to **easybits Extractor** for invoice data extraction. Returns structured data under `json.data` \u2013 including the `invoice_number` field that the validation step checks against."
      },
      "typeVersion": 1
    },
    {
      "id": "b441edbc-fd7e-4964-bedc-243fb0943706",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 400,
        "content": "## \u2705 Validation Check\nChecks whether `invoice_number` was successfully extracted. Uses the **is empty** operator, which catches real nulls, undefined values, and empty strings in one condition.\n\n- **True branch** \u2192 extraction failed \u2192 Slack alert to finance\n- **False branch** \u2192 extraction succeeded \u2192 file is archived to Google Drive"
      },
      "typeVersion": 1
    },
    {
      "id": "bdb5836d-89a6-44d8-aaa3-7babd0c220a2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 400,
        "content": "## \ud83d\udcac Slack Alert\nPosts a failure notification to the finance channel with the sender's email, the original subject line, and a timestamp. This gives Sarah immediate context to find the invoice in her inbox and enter the data manually."
      },
      "typeVersion": 1
    },
    {
      "id": "7fea6bf2-da35-4193-86ad-89aa3ab02344",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 432,
        "content": "## \ud83d\udd17 Merge: Reattach File\nThe Extractor node drops the binary attachment from the item. This Merge node (combine by position) reunites the successful extraction data with the original file from the Gmail Trigger so it can be archived in Drive with the extracted metadata intact."
      },
      "typeVersion": 1
    },
    {
      "id": "a8e9200b-84ae-4b25-bce2-63601065c681",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 432,
        "content": "## \ud83d\udcc1 Upload to Invoice Folder\nOn successful extraction, uploads the original attachment to the **Invoices** folder in Google Drive for archival. Failed extractions are handled separately via the Slack alert and don't land here \u2013 only clean, validated invoices get stored."
      },
      "typeVersion": 1
    },
    {
      "id": "fc3b8753-c6d4-4291-a0a6-028cf6d7ec45",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -512
      ],
      "parameters": {
        "width": 848,
        "height": 1456,
        "content": "# \u26a0\ufe0f easybits Extractor \u2013 Error Handling Workflow\n\n## What This Workflow Does\nMonitors incoming invoice emails and catches extraction failures before they slip through. When **easybits Extractor** can't extract the invoice number from an attachment, the workflow sends a Slack alert to finance so nothing gets lost. Successfully extracted invoices are archived to Google Drive \u2013 only clean, validated files land there.\n\n## How It Works\n1. **Gmail Trigger** \u2013 Polls for new emails with attachments every minute\n2. **Extraction** \u2013 The attachment is sent to easybits Extractor\n3. **Validation** \u2013 An IF node checks if `invoice_number` was successfully extracted\n4. **On failure** \u2013 A Slack alert is sent to finance for manual review\n5. **On success** \u2013 The file is merged back with its extracted data and archived to Google Drive\n\n## Why This Matters\nExtractor returns `null` when it can't confidently identify a data point \u2014 which is the right behavior (better than hallucinating a value). But without a safety net, those nulls can propagate into your Sheets, your approval flow, or your accounting system. This workflow makes silent failures visible.\n\n## Setup Guide\n### 1. Set Up Your easybits Extractor Pipeline\n1. Go to [extractor.easybits.tech](https://extractor.easybits.tech) and create a pipeline for invoice extraction\n2. Make sure your pipeline includes an `invoice_number` field (this is the field the validation step checks)\n3. Click **\"Auto-Map Fields\"** to let the Extractor suggest fields from a sample invoice, then review and save\n4. Copy your **Pipeline ID** and **API Key** from **Pipeline Details \u2192 View Pipeline**\n\n> \ud83d\udca1 **Tip:** You can validate against any field that's critical for your use case \u2013 just swap `invoice_number` in the IF node for whatever field you define as mandatory (e.g. `total_amount`, `vendor_name`).\n\n### 2. Install the easybits Extractor Node\n- **n8n Cloud:** The node is **verified** \u2013 just search for \"easybits Extractor\" in the node panel\n- **Self-hosted:** Go to **Settings \u2192 Community Nodes \u2192 Install** and enter `@easybits/n8n-nodes-extractor`\n\n### 3. Connect Your Credentials\n1. **Gmail Trigger: New Invoice** \u2013 Add your Gmail OAuth2 credential and confirm the polling interval\n2. **easybits: Extract Invoice Number** \u2013 Enter your Pipeline ID and API Key\n3. **Slack: Notify \u2013 Extraction Failed** \u2013 Add your Slack credential and update the target user or channel\n4. **Upload to Invoice Folder** \u2013 Add your Google Drive credential and select the folder where archived invoices should land\n\n### 4. Adjust the Validation Field (Optional)\nThe IF node currently checks `{{ $json.data.invoice_number }}` with the **is empty** operator. If your pipeline uses a different critical field, update this expression to point at that field.\n\n### 5. Activate & Test\n1. Click **Active** in the top-right corner of n8n\n2. Send yourself a test email with an invoice that's hard to read (blurry photo, scanned copy with poor contrast) to force an extraction failure\n3. Confirm you receive the Slack alert\n4. Send a clean invoice to confirm the success branch uploads correctly to Google Drive\n\n## \ud83d\udd04 Extending This Pattern\nThis error handling branch can sit in front of any workflow in the easybits series:\n- **Invoice Approval Pipeline** \u2013 catch failed extractions before they hit Slack approval\n- **Document Classification Pipeline** \u2013 flag documents that couldn't be classified confidently\n- **Receipt-to-Sheet** \u2013 prevent null rows from polluting your expense tracker\n\nThe pattern is always the same: Extractor \u2192 IF (is empty) \u2192 error branch alongside your main path."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Upload to Invoice Folder": {
      "main": [
        []
      ]
    },
    "Gmail Trigger: New Invoice": {
      "main": [
        [
          {
            "node": "easybits: Extract Invoice Number",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge: Extracted Data + File",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge: Extracted Data + File": {
      "main": [
        [
          {
            "node": "Upload to Invoice Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate: Invoice Number Present": {
      "main": [
        [
          {
            "node": "Slack: Notify \u2013 Extraction Failed",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge: Extracted Data + File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "easybits: Extract Invoice Number": {
      "main": [
        [
          {
            "node": "Validate: Invoice Number Present",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Monitors incoming invoice emails and catches extraction failures before they slip through. When easybits Extractor can't extract the invoice number from an attachment, the workflow sends a Slack alert to finance so nothing gets lost. Successfully extracted invoices are archived…

Source: https://n8n.io/workflows/15098/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

Receive any business document via email. The attachment is automatically classified (Invoice, Contract, or Purchase Order) using easybits Extractor, then routed down the correct path where a second Ex

@Easybits/N8N Nodes Extractor, Gmail Trigger, Google Drive +2
Email & Gmail

Automatically process labeled emails with attachments into organized Google Drive folders Teams or Individuals needing to: Automatically sort invoices, receipts, and files. Organize client documents b

Google Drive, Gmail Trigger, Gmail +1
Email & Gmail

Gmail Attachment Sender Folder - Final Working. Uses gmailTrigger, gmail, httpRequest, googleDrive. Event-driven trigger; 12 nodes.

Gmail Trigger, Gmail, HTTP Request +1
Email & Gmail

Attachments Gmail to drive and google sheets. Uses stickyNote, gmailTrigger, httpRequest, googleDrive. Event-driven trigger; 17 nodes.

Gmail Trigger, HTTP Request, Google Drive +5
Email & Gmail

This workflow takes new Outlook emails with attachments and helps archive the relevant files in DATEV DMS.

Microsoft Outlook Trigger, @Klardaten/N8N Nodes Datevconnect, Slack +1