Scheduled workflow: "Generate CSV file" sometimes produces a CSV with only headers (0 rows)

Hi everyone,

Follow-up to my earlier thread: Scheduled workflow: generate one CSV from a table and send it once via API. The workflow works, but it fails intermittently and I can’t find a pattern.

Setup (scheduled workflow, every hour):

  1. Query “Clientes (activos)” → Loop → Generate CSV file → Call API (POST the file URL to my server)
  2. Query “Clientes (inactivos)” → Loop → Generate CSV file 2 → Call API

What happens

  • In 10 of the last 30 hourly runs, the active clients CSV came out with only the header row and no data rows (1,921 bytes). A normal one is ~943 KB, ~660 rows.
  • My server rejects the empty file, so Call API returns 400 and the run is marked as failed.
  • The inactive clients CSV (same table, ~2,500 rows, ~2.7 MB) came out fine in every one of those runs.
  • I changed nothing in the app between runs that work and runs that don’t. For example, on Oct 11 (UTC-5) the 10:05, 11:06, 17:05, 18:04, 20:05 and 21:05 runs failed, and the runs in between succeeded.
  • I downloaded the bad file hours later and it still had only the headers, so it isn’t a matter of reading it before Glide finished writing it.

Questions

  1. Has anyone seen “Generate CSV file” return 0 rows intermittently in a scheduled workflow?
  2. Could the query come back empty when the columns it filters on (computed columns) aren’t evaluated yet on the backend at run time?
  3. Is there a way to check the row count and retry before the Call API step, given that scheduled workflows have no Wait step?

Thanks!

I would add an IF block that checks the status of the Query (empty/not empty), and then only proceed with the Generate CSV step if the Query is not empty.

I’ve had issues like you describe for Generate CSV on a scheduled workflow. I never found an answer for why it would fail. The closest I could guess is that either the file was too big or the compute time hit a timeout when computing all of the table calculations to make the file. For my particular complicated app, it kept erroring out at around 800 rows. I ended up abandoning it because the troubleshooting steps were inconclusive. Oddly enough, the same action worked perfectly when it was a user triggered action (pointing to a server timeout).

i tried that and didnt work:

yeah i think glide is seriously getting behind with all this bugs and limitations

Hi @Mateo :slight_smile:

The problem

Complex calculations colmuns (such as Queries, Relations, If → Then → Else, Rollups, JavaScript) might not have time to get evaluated when the server tries to Generate CSV resulting in an empty file (with headers).
I’m not sure that’s a viable explanation in your specific case, but I’ve also faced this kind of unpleasant reality in the past for that reason.

A suggestion

After having a look at your recent posts, I think you’re trying here to synchronize your Supabase (PostgreSQL) data with Glide. Especially, you’d like to update your customer data from Glide to Supabase.
If I’m not mistaken, then maybe you should consider another approach in order to make it more robust and more direct:

  1. Add a flag to identify recently updated customers. This way, you’ll only push relevant data, not the whole dataset (or the whole active and inactive subsets more precisely).
    A very simple way to do that is to add a Last modification date column, populated with Current Date/Time triggered by the User action (such as opening the Edit Screen for example).
  2. Create a JSON object containing all updated rows and data. Considering your previous answers, I’ll simply point out the way: JSON Object column → Query on the same table with a filter on Last modification date to only get updated rows → Joined List → Template (for example).
    The goal here is to have all updated rows, in a JSON array (starting and ending with [ and ]) format and in a single cell (limited to 1 million characters though… must be mentioned).
  3. Use a Call API to… send your data directly to Supabase without the Hostinger step. Using a Prefer: resolution=merge-duplicates header, you’ll upsert (update or insert) your fresh data from Glide to Supabase.
    The URL must be changed to target Supabase. You’ll find it your Supabase backend.
    If Hostinger is used for something else, steps 1. and 2. are still relevant: only send fresh data, not the whole package :wink:

I hope you’ll find that useful. It’s a 100% Glide/Supabase logic, no Make/Zapier/n8n/scripts (what about Hostinger?) idea :smiley:

One thing I’d check before switching from full exports to changed rows: can customers ever be deleted in Glide, or are they always marked inactive? Upserts would carry the inactive flag across, but a hard-deleted row would disappear from the next batch and remain in Supabase. If deletion is possible, a soft-delete flag or separate deletion log would keep that case from silently drifting.