Critical: Table changesetArray flattens nested Firestore objects to strings β€” breaks downstream app

  1. My goal: Continue using my code

  2. Issue: When I save js object with only one attribute to firebase it flattens it to string.

  3. Steps I've taken to troubleshoot: I confirmed that the same code that worked 2 days ago changed it’s behavior.

  4. Additional info: (Cloud or Self-hosted, Screenshots) Cloud based.
    project https://healthspan2024.retool.com/editor/1e61194a-b1b1-11ef-b0b8-034a5dba11fb/Coach%20-%20Scheduling%20tool/Plan

    My app expects a specific format for JSON, so this change broke a bunch of my workouts. Although I know how to fix it in one place, I am not sure which of my projects and workflows are affected.

    Summary

    When editing a row in a Retool table backed by Firestore, changesetArray is serializing nested map/object fields as plain strings instead of preserving the original object structure. This started happening recently (between March 18-25, 2026) with no changes to our app code.

    Setup

    • Retool Cloud (not self-hosted)

    • Data source: Firestore (Google Cloud Firestore)

    • Table: Editable table displaying Firestore documents

    • Write method: JavaScript query loops through table.changesetArray, processes each doc, then calls an updateFirestore query to merge changes back

    The problem

    We store a ContentLink field on Firestore documents as a nested object:

    {
      "youtube": "https://www.youtube.com/watch?v=abc123",
      "description": null,
      "isPortrait": false,
      "other": null
    }
    
    

    The ContentLink column is configured as format "link" in the table but is not editable and not visible to users. When a user edits a different column in the same row (e.g., changing a DayIndex dropdown), the changesetArray entry for that row sometimes includes ContentLink β€” but serialized as a plain URL string:

    "https://www.youtube.com/watch?v=abc123"
    
    

    Our save handler passes this through to updateFirestore (merge), which overwrites the nested object in Firestore with the flat string. Our mobile app expects a map and crashes.

    What we've confirmed

    1. Our Retool app code has not changed. We diffed JSON exports from Nov 2025, Mar 11, and Mar 26 β€” the save handler, cleanup function, and Firestore query are byte-for-byte identical.

    2. This was not happening before. We scanned ~10,000 Firestore documents across 5 weeks. The same save operation (updateFirestore via changesetArray) ran 162 times in the week of Feb 23 with zero flattened objects. By the week of Mar 30, the flattening rate was 58% on the same code path.

    3. The behavior is deterministic and reproducible. Every edit made through the Retool table's save path flattens the nested object. We initially thought it was intermittent, but the cases where the field survived turned out to be edits made through our Flutter mobile app (which uses a targeted Firestore .update() on only the changed field, bypassing Retool entirely).

    4. It specifically affects youtube URLs. We compared 127 documents that went through the same "Update" save path. Every document where ContentLink contained a youtube key with a URL was flattened (74/74). Every document where ContentLink contained only an other key (blog article link) was preserved (53/53). The table component appears to be extracting the youtube URL specifically.

    5. The column is not editable. The ContentLink column is not visible in the table UI. Users only edit DayIndex. Yet ContentLink appears in changesetArray entries.

      Thank you,
      – Mia

Hey @Healthspan_Technical - thanks for reaching out. It doesn't look like we've changed anything in the product that would potentially be responsible for this. I've tried replicating the behavior, as well, without any luck.

Are you able to share a screen recording or JSON export of your app? One that includes hard-coded query results, ideally. It might also be helpful to have you join Office Hours next week, if it can wait until then!

Here is my JSON export Dropbox

Here are screen recordings:

Dropbox

Dropbox 2

We found the problem; it was on our side.
Sorry for bothering!!!

We accidentally deleted a table column instead of hiding it, but our code had an override in case this column is empty, so when the changes array changed, our code continued to work, and that is why it was so confusing.

Thank you for your help and fast reply!!

1 Like