What your reverse ETL syncs and dbt models break when a Salesforce field or value changes
Short answer. When a Salesforce field's API name changes, Fivetran treats it as a new column plus a deleted one: the old warehouse column stays, stops getting values, and every dbt™ model that reads it keeps building while quietly returning nulls. When a picklist value is replaced and the old one is retired, dbt filters on the old string go quiet, and any Hightouch or Fivetran Activations (formerly Census) sync that writes the old value into a restricted picklist starts getting rows rejected by Salesforce. Nothing in Salesforce warns you, because Salesforce only checks references inside Salesforce. Before the change, list every Fivetran column, dbt model and sync mapping that uses the field or the exact value, and fix them in the right order.
The rest of this page shows why, using each vendor's own documentation, then walks through one example end to end and gives a checklist.
Why doesn't Salesforce warn me?
Salesforce checks references inside the org. Its help article on changing a field's API name lists Apex classes, triggers, Visualforce and Apex callouts as the places to search, and tells you to update external integrations yourself (Change the API name of a field). Deleting a custom field is blocked only when another field, a field update or Apex references it (Delete a Custom Field). A Fivetran connector, a dbt project and a reverse ETL sync are all outside that check.
What does Fivetran do when a Salesforce field is renamed or deleted?
Fivetran's destination docs say a renamed column is handled as two changes: a new column and a deleted column (Supported Destinations). For a deleted column, Fivetran says it generally leaves the column in the warehouse with its old data and writes NULL from then on; a few connectors null out all of its values instead (Supported Destinations; Why Do Deleted Source Columns Still Appear in the Destination?). If the table is later re-synced, the old data in the deleted column is wiped (What Happens When a Column Is Deleted From a Table in the Source?).
Two settings decide whether the renamed column shows up at all:
- Schema change handling. With "Allow all new data" or "Allow new columns", the new column is added. With "Block all new data", new columns on existing tables are not synced (Connection Schemas).
- Notifications. You can ask for an email when a new column is detected, but Fivetran says it does not send emails for deletions in the source (Connection Schemas).
So after an API-name change, the old column goes quiet without an alert, and the new one may or may not land, depending on a setting most teams set once and forget.
Why does my dbt model still run after a Salesforce field rename?
Because the column it selects still exists. dbt sources name the tables your loader writes, and models read them through {{ source() }} (Add sources to your DAG). The source table is still there and the old column is still in it, now filling with NULL (per the Fivetran behavior above). Our reading of the two docs together: the model compiles, runs and passes a source freshness check, because rows are still arriving. Only the values are missing.
What does catch it, from dbt's own docs:
- Data tests. dbt ships
not_nullandaccepted_valuesas generic tests (Add data tests to your DAG). Anot_nulltest on the column fails once new rows arrive empty. Anaccepted_valuestest fails when a new picklist value appears that the list does not include. - Model contracts check the shape of a model (columns and types) and fail the build if it does not match (Model contracts). A contract does not check values, so it will not catch a picklist value change.
If the old column is later removed from the warehouse (for example by a re-sync or by dropping blocked columns, both described in the Fivetran pages above), models that select it by name would then fail with a missing-column error from the warehouse. That is a later, louder failure; the quiet null period comes first.
Why is Hightouch or Fivetran Activations getting a restricted picklist error from Salesforce?
A restricted picklist only accepts values an admin has defined, including through the API (Create a Custom Picklist Field). Salesforce's own troubleshooting for this error says to check that the value exists in the picklist, is spelled the same, and is not inactive, and notes that integrations must send the value's API name, not its label (Account Engagement Sync Error: Invalid Picklist Value).
- Hightouch lists
INVALID_OR_NULL_FOR_RESTRICTED_PICKLISTas a sync error caused by writing a value that is not in the picklist's allowed values (Salesforce, Hightouch Docs). Hightouch field mappings can also write a static value, the same constant for every record (Field mapping). A static value is easy to forget because it lives in the sync, not in your model. - Hightouch also warns that if a mapped Salesforce field is renamed or deleted, the mapping breaks without an error (Salesforce, Hightouch Docs).
- Fivetran Activations records that Salesforce refuses show up as "rejected" records in the sync's Sync History, with a sample and the reason the destination gave (Syncs, Activations Docs). Its Salesforce page says the error message comes back from Salesforce when a write is refused (Salesforce, Activations Docs). Field mappings can be a column or a constant value (Create a new sync).
In both tools the sync keeps running. The damage is the set of records that silently did not update.
One example, end to end
All names here are made up.
A RevOps team has a restricted picklist Region__c on Account and Lead with values including EMEA. Fivetran syncs Account into Snowflake (it would look the same in Google Cloud BigQuery). A dbt model fct_pipeline_by_region filters where region__c = 'EMEA' for the European pipeline dashboard. A Hightouch sync for European event sign-ups writes the static value EMEA into Lead.Region__c, and a Fivetran Activations sync does the same with a constant value.
Change 1: the value. The team wants Europe instead of EMEA. Following Salesforce's guidance, an admin adds Europe, uses Replace to move existing records from EMEA to Europe, then deactivates EMEA. Replace updates every existing record; a plain rename would only have changed the label, not the API name (Difference between renaming and replacing a picklist value).
- Fivetran: as records change, the warehouse
region__ccolumn picks upEuropeon later syncs (our inference: the records changed, so the loader carries the new value). - dbt:
fct_pipeline_by_regionstill builds. ItsEMEAfilter now matches fewer rows and eventually none. The European dashboard drifts toward zero with no failed job. Anaccepted_valuestest listing the old values would fail onEurope, which is the warning you want. - Hightouch: the static
EMEAmapping now targets an inactive value in a restricted picklist. Salesforce refuses those rows withINVALID_OR_NULL_FOR_RESTRICTED_PICKLIST. - Fivetran Activations: the constant
EMEAmapping gets the same refusal, and the rows land under rejected records in Sync History.
Change 2: the field. Later, someone changes the API name from Region__c to Sales_Region__c.
- Fivetran: treats this as a new column
sales_region__cplus a deletedregion__c. The old column keeps its history and gets NULL for new rows. If the connector is on "Block all new data",sales_region__cnever arrives. No email is sent about the deletion. - dbt: every model reading
region__ckeeps building, with nulls for new and changed records. Anot_nulltest is the first thing that fails. If someone re-syncs the table, the old column's history is wiped too. - Hightouch: a mapping to
Region__cbreaks without an error, per Hightouch's docs. - Fivetran Activations: check every sync that maps
Region__c; we did not find an Activations doc describing what happens to a mapping when the Salesforce field is renamed.
Neither change produces a red error in Salesforce. Each failure surfaces in a different tool, days or weeks apart.
Checklist before you change a Salesforce field or picklist value
- Decide label or API name. Changing only a picklist value's label leaves the API name alone; Replace and API-name changes alter what integrations see (Salesforce Help).
- Search your sync mappings for the exact value, including static or constant values in Hightouch and Fivetran Activations. Model columns are not the only place a value lives.
- Check whether the target picklist is restricted. If it is, any sync still writing the old value will be refused once that value is inactive.
- Add the new value first, update syncs and models, then deactivate the old value. Do not deactivate first.
- Find every warehouse column fed by the field in your Fivetran connector, and check the connector's schema change setting. Under "Block all new data", a renamed field never lands.
- Search your dbt project for the column name and the literal value (filters,
casestatements, seeds, macros). - Add or update dbt tests:
accepted_valueson picklist-derived columns,not_nullon columns you depend on. - Do not re-sync the Fivetran table right after a rename unless you mean to lose the old column's history.
- Watch the first syncs after the change: Hightouch sync errors and Fivetran Activations rejected records, plus row counts in models that filter on the value.
How Meshie checks this before you ship
Meshie is a GTM agent that checks its own work. It reads configuration only, never records or table rows, and it never writes to Salesforce, your warehouse, Fivetran, dbt or your syncs. It never triggers a dbt job or a sync, and it never deploys.
What it reads for this chain (all integrations below are Beta):
- Fivetran (Beta): connectors and schema config. It links each Fivetran column to the Salesforce field it comes from (read from config when the schema config names the Salesforce column, otherwise matched by name) and to the warehouse column it lands in.
- Snowflake and Google Cloud BigQuery (Beta): tables, views, columns and view dependencies. Never rows.
- dbt platform, formerly dbt Cloud (Beta): models, sources, dependencies and documented columns from a job's latest successful run. Sources link to warehouse tables (read from config). A model links to an upstream column only when the column is documented with the same name (matched by name). Meshie sees model-to-table dependencies and documented columns, not full column-level lineage, and it does not claim to read the filter values inside a model's SQL. A
where region__c = 'EMEA'is still something to search for yourself. - Hightouch and Fivetran Activations(Beta): syncs, models and sources, destinations and each sync's field mappings. A sync is linked to the exact Salesforce field it writes, and a sync that writes a fixed value into a picklist is linked to that exact picklist value. Fivetran Activations sync filters are not read.
Every link shows the config it came from and how it was found (read from config, matched by name, or observed), and every answer lists what it could not check.
You can ask for a change in plain English, in the app, in Ask, or from any agent that speaks MCP. Meshie classifies it (retiring fields, picklist changes, field rollouts or validation rules), drafts it, shows the blast radius across your connected systems and gives a verdict: safe to hand off, needs review, or blocked. You ship it through your own process. On the next scan, Meshie compares what changed with what it predicted. The Free plan includes 10 change requests a month.
See it on real output: the sample report traces one picklist value (SaaS - Enterprise on Industry) from Salesforce into HubSpot, Fivetran Activations (formerly Census) and Hightouch, and shows systems it detected but was not connected to, so you can see how gaps are listed rather than hidden.