Google sheets keeps on saying coloums has been been changes i have refreshed deleted the node added a new one same isssue

Column names were updated after the node’s setup
Refresh the columns list in the ‘Column to Match On’ parameter. Updated columns: email → user_id, phone → email, channel → phone, last_message → channel, intent → last_message, is_lead_related → intent, status → is_lead_related, last_updated → status i got this error i have refreshed columns and it still hass the issue what do i do

Describe the problem/error/question

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)

Share the output returned by the last node

Information on your n8n setup

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

Hi @SAM_M

Please can you share a screenshot of your google sheets node properties. This error generally means that you or someone changed the google sheets columns header in your sheet after you had setup your node. This could be either name changes or changing the order of the columns.

did you manage to fix it? I’m having the same issue. even after deleting the node, adding a new one, and remapping everything

The node caches column mappings internally, so deleting and re-adding doesn’t always fix it. Open the Google Sheets node, click into the “Column to Match On” dropdown, and use the small refresh icon right next to it. That forces n8n to re-read the actual sheet headers. If it still persists, check if any column header in the sheet has a trailing space or was renamed since you first configured the node.

Checking on when this is going to get fixed. Sheets Node v3 does not have this problem. We need columns to be able to be dynamically referenced. This is breaking multiple of my flows that need to be able to put the same data in multiple sheets with different column orders but same column names. Please allow the next version of Google Sheets Node to not cache columns.

TylerH, the useful repro is the same column names with different order across two sheets, not the older “rename a header then refresh” case.

Can you post the smallest example with Sheet A headers, Sheet B headers, the exact Google Sheets operation/node version, and whether the same workflow works in v3? That gives the n8n team a clean cache-vs-dynamic-mapping test instead of another refresh-columns loop.

One thing that usually fixes the stuck column cache: in the Google Sheets node, switch “Mapping column mode” from “Map automatically” to “Map each column manually”, save, then switch it back to “Map automatically” - this forces n8n to discard the cached schema and reload it fresh from the sheet. If that still doesn’t work, export the workflow JSON, find the Google Sheets node’s parameters, and manually delete the schema and schemaType keys from the JSON, then reimport. That completely clears the embedded column cache regardless of what the UI refresh does.

We ran into the same error while packaging n8n workflows, and in our case the trigger was not a change on the spreadsheet side. Two measurements in case they help narrow it down.

1. Re-selecting the Document or Sheet inside the node silently resets the column config.

Reproduced twice on self-hosted n8n 2.31.5. The moment we picked the Document/Sheet again from the dropdowns, the node lost:

  • mappingMode (autoMapInputData reverted to an empty manual mapping)
  • matchingColumns
  • options.cellFormat (RAW reverted to the default)

No error, no warning — the node still looks configured. We saw the same path wipe the saved matchingColumns and values of a defineBelow mapping as well. So “column names were updated after the node’s setup” can fire even when nobody touched the sheet headers: opening the node and re-picking the sheet is enough to trip it.

2. What worked for us was avoiding the dropdown entirely.

Instead of selecting from the list we set documentId to By URL (filled from an expression, with the sheet URL held in one settings node) and sheetName to By Name with a fixed string. With no dropdown selection anywhere in the flow, there is no re-selection event to reset the mapping. That is prevention rather than repair, so it complements Jay’s fix of stripping schema / schemaType out of the exported JSON, which is what we would use to recover a node that is already broken.

3. Worth checking cellFormat after any such reset.

When it silently reverts from RAW, written values get re-interpreted. On a separate workflow we measured that a period label written with RAW comes back byte-identical on read-back — which is exactly what an idempotency/re-send guard key depends on. With the default format it can be parsed into something else. So this reset can quietly corrupt data, not just break the mapping.

Caveat: these are measurements from self-hosted 2.31.5 / 2.32.6. We have not evaluated the Sheets node typeVersion, so I can neither confirm nor contradict the point above about v3 not having the issue.

Yeah sometimes it happens and my workaround for it is that I do create a config node (js code node or fields node) that should contain the columns names and in the google sheet node itself the columns names should be “expression” field and then we use the column names from the config node.

@appunitsai That config-node pattern is one I’d want to split into its two possible wirings, because one of them fails silently and the other is solid.

Measured on our side — local n8n 2.30.7, 2026-07-22, and we have not re-tested this specific behaviour on 2.31.x / 2.32.x.

Wiring A — the config node feeds the column names into the key slots. With the Sheets node in Map Each Column Manually (defineBelow), an expression placed in the column key / name slot is not evaluated. It’s dropped silently — no error, no warning, the column just never receives its value. Expressions in the value slot evaluate normally; it is specifically the key side that gets ignored.

Wiring B — the config node feeds a Code node. Let the config node decide the names, but have a Code node emit the finished row object with literal keys, and set the Sheets node to Map Automatically (autoMapInputData). You get the same dynamic behaviour, and nothing depends on key-slot expression evaluation.

So if your config node is feeding the values while the column names are typed literally, you’re on the safe path. If it’s feeding the column names into the key fields, that’s the one worth double-checking on your version — the failure mode is a row that lands with those columns blank, rather than an error.

Flagging it because it’s the same family as the problem this thread opened with: nothing in the UI tells you it didn’t take.