Google Sheets Search Rows returns 0 bundles — Router cannot route new-member path

:bullseye: What is your goal?

I need my webhook to check Google Sheets for an existing member email. If the email exists, return {"duplicate":true}. If it does not exist, add the member as a new row and return {"duplicate":false}.

:thinking: What is the problem & what have you tried?

I am building a webhook-driven member registration scenario.

The scenario is intended to do this:

  • If the incoming email already exists in Google Sheets, return {"duplicate":true}.
  • If the email does not exist, add the member as a new row and return {"duplicate":false}.

My current scenario is:

Receive member (Webhook)
→ Router

Router route 1:
Google Sheets – Search Rows
→ Webhook Response

Router route 2:
Google Sheets – Add a Row
→ Webhook Response

The Google Sheet has these columns:

id | firstName | email | situation | interest | consentCommunications | consentAt | locale | source | createdAt | status

Email is column C.

Search Rows is configured with:

  • Spreadsheet: Sheet1
  • Table contains headers: Yes
  • Column range: A1:Z1
  • Filter: email (C) equals the incoming webhook email
  • Limit: 1

What works:
When I test with an email that already exists, Search Rows returns 1 bundle and the duplicate Webhook Response works. It returns:
{“duplicate”:true}

The problem:
When I test with a completely new email, Search Rows returns 0 bundles. The Add a Row module does not execute. It remains blank in the execution results.

I tried using Router filters:

  • Total number of bundles = 0 for the new-member route
  • Total number of bundles > 0 for the duplicate route
  • Fallback set to No

I also tried placing Search Rows before the Router, but when it returned 0 bundles the Router still had nothing to process.

I am currently using the Google Sheets Search Rows module and do not see an option to continue execution when no rows are found.

I would like to know the recommended architecture for handling this situation while preserving the original webhook bundle:

Existing email → duplicate response
New email → Add a Row → new-member response

I would appreciate a concrete module-by-module solution using the current Make/Maia modules.

:clipboard: Error messages or input/output bundles

For an email that already exists, Google Sheets → Search Rows returns 1 bundle. The output includes the matching row and shows:

For a new email, Google Sheets → Search Rows returns:

  • Total number of bundles: 0

The Add a Row module then has no execution result.

One of the new-member tests used:

email: [email protected]

The Search Rows execution for that test showed:

Output:
Bundle 1 Collection
Total number of bundles: 0

Credit usage:
1 credit

The duplicate test successfully returned from the Webhook Response:

{“duplicate”:true}

The Webhook Response module also showed a warning in an earlier configuration:

“Response can’t be processed when scenario is not executed immediately on data arrival.”

The webhook is now configured to run immediately as data arrives.

Hi @Patrick_Harrison ,

The Workflow should be like:

  1. Webhook
  2. Google Sheet Search Email (add TRIM formula and limit to 1)
  3. Router
  • Path A:
    • Filter Bundles = 0 (select field named as Total number of Bundles)
    • Add ROW in Sheet or Whatever you need
  • Path B:
    • Filter Bundles > 0 (select field named as Total number of Bundles)
    • Update ROW or Whatever you need

Let me know if you need any further help!

Thanks, known Anonymous

You are dead wrong. And the AI model you use to answer all over the community has mixed Make with n8n, there is no Always Output Data option in Make.

The key detail is that a router can only route bundles it receives. When Search Rows returns zero bundles, nothing reaches the router.

One workable pattern is: Webhook → store the incoming fields in variables → Search Rows → Array Aggregator → Router. The aggregator should emit one bundle containing an empty array when there is no match. Then route on array length = 0 for Add a Row, and > 0 for the duplicate response. Use the stored webhook values for the new row.

I’d also normalize the email before searching (trim + lowercase) and add a final unique-key check before writing, so two near-simultaneous registrations cannot create duplicates.

Search rows finding nothing doesn’t mean it produces no bundles. It returns a bundle with no items inside.

The actual solution is already posted above.

Thanks for the correction. You’re right: in Make, Search Rows exposes an output bundle with an empty items collection, so the existing Total number of bundles route shown above is the simpler solution. My added aggregator step was unnecessary here.

Hi, Patrick!

I reproduced this in a minimal Make scenario. One important detail in this test was that the Array Aggregator did not produce an array with length 0. It produced an array with length 1 containing one item with an empty Row number. Because of that, I routed on whether Row number exists rather than on the array length.

Here is the setup I tested

Webhook
→ Search Rows
→ Array Aggregator
→ Router
├─ Row number Exists
│ → Webhook Response {“duplicate”:true}
└─ fallback
→ Add a Row
→ Webhook Response {“duplicate”:false}

Array Aggregator:

  • Source module: Search Rows
  • Target module: Custom
  • Aggregated fields: email, Row number
  • Stop processing after an empty aggregation: OFF

Duplicate route:
Array[] → Row number → Exists
New-member route:
Fallback

In Add a Row, map firstName and email directly from the original Webhook bundle, not from the Array Aggregator, because the aggregated item is empty when no row is found.

Three cases were tested:

  • Existing email → {“duplicate”:true}, no row added
  • New email → {“duplicate”:false}, one row added
  • The same email again → {“duplicate”:true}, no second row added

There are some screenshots attached to illustrate the proccess

Again. You don’t need an array aggregator. You need the filter to check if the total number of bundles is zero or not.

Again, the correct solutions is already posted above, stop spamming AI generated replies.

You’re right, Champion. My apologies. The simpler scheme also works. And indeed it’s better.
I didn’t intend to upset you :wink: