Module 1: Why Version Your Workflows
5. What changes and what breaks when you reimport
Description
By the end of this lesson you will be able to look at a workflow's JSON and point out, one by one, every field that would break if you naively imported it into another n8n instance: credential IDs, node IDs, webhook identifiers and URLs, and references to environment variables. You will understand why "I exported it and imported it" is an operation that fails silently —with no big error to warn you— and what you have to control so it doesn't happen to you.
This matters because it's the most costly trap in all of n8n automation, and the one most people learn the hard way. You move a workflow that used to work, import it somewhere else, see that every node arrived, turn it on confidently, and days later discover it never really worked: the AI agent had no credential, the CRM call pointed to nothing, the webhook changed address and whoever was calling it can no longer find it. All of that could have been avoided if you'd known, before moving it, exactly what was going to break. This lesson gives you that list.
Connection to the module: lesson 4 taught you to read the JSON and to tell stable fields apart from volatile ones, and it closed by pointing out that some volatile ones —credentials.id, the node id, the webhookId— are "dangerous volatile" fields. This lesson explains exactly why they're dangerous and what disaster they cause. It's the technical culmination of lessons 3 and 4's argument: not only does export/import fail to version (lesson 3) and the JSON have volatile fields (lesson 4), but those volatile fields actively break when you move the workflow. And it's what makes everything that follows essential: separating credentials from the workflow (Module 3) and handling credentials per environment (Module 4) are, at bottom, the solutions to the problem this lesson installs. Lesson 8's project asks you to write the "portability risk note," which is basically the result of applying this lesson to order-triage.
Importing a workflow is like moving an old phone's contacts
Imagine you buy a new phone and want to carry over your speed dials from the old one. On the old phone you had set up: speed dial 1 = your mom, speed dial 2 = work, speed dial 3 = your best friend. Now suppose that, instead of copying the actual phone numbers, someone copies only the speed-dial labels: "speed dial 1," "speed dial 2," "speed dial 3."
On the new phone, those speed dials are empty —or worse, they already had other numbers assigned. You press "speed dial 1" expecting your mom and you call the wrong number, or nobody. The labels copied perfectly. The numbers did not. And the phone doesn't warn you: everything looks fine, all three speed dials are there, until you press one and call the wrong person.
That's almost exactly what happens when you import a workflow. The JSON copies the references —"use credential 27," "the node has ID such-and-such," "this webhook is at this path." But those references only mean something on the original instance. On the new instance, credential 27 doesn't exist or is something else; the node's ID gets regenerated; the webhook gets a new address. The nodes all arrive, look perfect on the canvas, and the workflow is broken on the inside, with not a single error message to tell you until you run it.
Remember lesson 4's idea: the JSON stores references, not secrets or absolute identities. That design decision, good for security, is exactly what makes moving a workflow dangerous. What copies well is the "what" (which nodes, how they're connected, with what parameters); what breaks is the "which specific one from this instance" (which credential, which ID, which webhook address). Let's walk through the four fragile points, from the most common to the most subtle.
Fragile point 1: credential IDs
This is the one that breaks the most workflows, by far. Go back to a node's credentials section from order-triage:
"credentials": {
"httpHeaderAuth": {
"id": "27",
"name": "Cumbre CRM - Header Auth"
}
}
As you saw in lesson 4, that "id": "27" is not the secret: it's a number pointing to a credential saved in this instance's database. Here's the problem when you move it: credential IDs are assigned per instance, in the order you created them. Credential 27 on your instance is "Cumbre CRM - Header Auth" because it was the twenty-seventh one you created. On your coworker's instance, credential 27 might be the Gmail one, or might not exist because they only created five credentials, or might also be the CRM one but for a different account.
When you import the workflow, three things can happen, all bad:
- Credential 27 doesn't exist on the new instance. The node ends up pointing to nothing. When run, it fails with a missing-credential error.
- Credential 27 exists but is something else. The node points to the wrong credential —say, the Gmail one instead of the CRM one. When run, it fails confusingly, or worse, does something with the wrong credential.
- There's no credential 27 at all. The field is left blank and n8n shows the node with a "select credential" warning, which is the best-case scenario because at least it's visible.
Notice that order-triage has two credentials —the CRM one and the AI provider one on the AI Agent node— so it has this problem twice over. And because the name (name) does get copied, the node can look correct —it says "Cumbre CRM - Header Auth"— while the ID underneath points to emptiness. The name is the speed-dial label; the ID is the number that didn't copy.
This is reason number one why "I exported it and imported it and it doesn't work" is n8n's most common complaint. It's also why Module 4 devotes entire lessons to handling credentials per environment: the solution isn't "remember to manually reconfigure credentials every time," but a system where every environment has its credentials with a predictable identity.
Fragile point 2: node IDs
Every node has an id —that "a1b2c3d4-..." that looks like a barcode. n8n uses it internally to uniquely identify the node. When you import a workflow into another instance, n8n can regenerate those IDs: it assigns them new values to guarantee they're unique within the destination instance.
In most cases, this doesn't break anything visible, and that's why it's more subtle than the credentials problem. Remember that connections between nodes are described by the node's name, not its ID (lesson 4), so regenerating the IDs doesn't break the workflow's arrows. The flow keeps working.
So why does it matter? For two reasons:
First, for versioning. If the IDs get regenerated every time the workflow passes through an instance, the diff between two versions fills up with id changes that mean nothing —pure noise, as discussed in lesson 4. A workflow that goes back and forth between instances builds up an unreadable history if you don't control this. The fix is normalizing (Module 3): pinning or ignoring these IDs so they don't clutter the diff.
Second, for references that do use IDs. Although normal connections use names, there are places where something can refer to a node or an element by its ID —certain internal configurations, some expressions. If an ID changes and something was referencing it by that ID, that reference breaks. It's rare, but it happens, and it's the kind of error that takes hours to find because it isn't obvious.
The practical conclusion: node IDs don't usually break the flow on import, but they clutter the history and are an occasional source of hard-to-find failures. It's a low-grade "dangerous volatile" compared to credentials, but worth knowing about.
Check the behavior on your version. Whether n8n regenerates or preserves node IDs on import can depend on the version and on how you import (file, paste, CLI). Don't take this lesson's word for it: test it on your instance —export, import into another one, and compare the
ids— and confirm what your version does. Module 3 comes back to this with the CLI, which gives you more control than the editor's import.
Fragile point 3: webhooks
This is the one that breaks things outside n8n, which is why it can be the most expensive. order-triage starts with a Webhook node: the door orders come in through. A webhook is an internet address —a URL— that n8n publishes for an external system to call. When Cumbre's online store registers an order, it makes a call to that URL, and that triggers the workflow.
Here's the fragility. A Webhook node has two relevant things in the JSON:
- A
path—a part of the URL you define— for example"path": "order-triage". - A
webhookId—an identifier n8n generates— that "f4b9c2a1-..." you saw in lesson 4's skeleton.
n8n generates a test URL and a production URL for every webhook. The exact shape of that URL depends on your instance's address (its domain) and on these identifiers. And there's the problem: when you move the workflow to another instance, the webhook's URL changes, because the new instance has a different address and can generate a different identifier.
The consequence is the most treacherous of all: the imported workflow can work perfectly if you run it by hand from the editor, and still be broken for the real world, because the external system —Cumbre's store— keeps calling the old URL, the one from the original instance. Orders get sent to an address that no longer responds, or that responds with a different workflow. Nobody inside n8n sees an error: from the inside, everything looks fine. The error is outside, in the system calling a door that moved.
That's why moving a workflow with a webhook isn't just "importing it": it's importing it and updating every external system that calls it so it points to the new URL. That's coordination outside n8n, and it's exactly the kind of thing a portability risk note (lesson 8's project) needs to spell out, so nobody forgets it.
Check on your version and your deployment. The details of how a webhook's URL gets built, whether the
webhookIdgets preserved or regenerated on import, and how test URLs behave against production ones, depend on your n8n version and your deployment configuration (domain, proxy, base path). The documentation confirms there's a test URL and a production URL per webhook; confirm the fine details on your own panel. What doesn't change is the concept: the webhook's address is tied to the instance, and moving the workflow can change it.
Fragile point 4: environment variables and embedded values
The fourth point is quieter but just as real. A workflow can depend on values that live outside its nodes, or on fixed values written inside them, and moving the workflow doesn't carry those values along cleanly.
Environment variables. n8n lets a workflow read variables from the environment it runs in —for example, the CRM's base URL could come from a variable instead of being written into the node. The idea is good: it separates configuration from the workflow. But it means the workflow, on its own, is incomplete: it needs the destination instance to have the same variables defined. If you import the workflow into an instance that doesn't have them, the expressions that read them return empty, and the workflow behaves strangely with no clear error. (An important technical note that Module 3 goes deeper into: n8n 2.0 tightened access to environment variables from the Code node; there are rules about what can be read and how, and it's worth not depending on reading them directly from code.)
Embedded fixed values. The reverse: sometimes the CRM URL, a threshold, an account identifier are hand-written inside a node. Those do travel in the JSON —they're part of parameters, a stable field. The problem isn't that they get lost, but that they travel too well: if on the original instance that value pointed to the production CRM, importing the workflow into a test environment still points to the production CRM. In other words, your "test environment" writes to real data, which is exactly what you didn't want. This is the mirror problem of the previous one, and it's why Module 4 insists on pulling environment-specific values out of the nodes.
The underlying lesson here: a workflow is rarely self-sufficient. It depends on credentials, on variables, on addresses that live in the environment. Moving the JSON moves the workflow, but it doesn't move its environment, and the difference between the two is where the bugs hide.
Worked example: order-triage crosses over to a new instance
Let's put the four points together into one story. Cumbre's team wants to move order-triage from one person's instance to a new shared server. Someone does Download on the old instance and Import from File on the new one. Here's what they see, step by step, and what's happening underneath.
On import. The workflow appears complete on the new instance's canvas. The three nodes —the webhook, the CRM call, the AI Agent— are there, connected by their arrows, with their correct names. What the person sees: everything's fine. What happened underneath: n8n imported the references, not the credentials or the instance's identity. There was no big error. This is the moment of deception: it looks perfect.
Opening the CRM node. The person double-clicks "Get customer from CRM." The credential field shows a warning: the "Cumbre CRM - Header Auth" credential isn't selected, or it shows up in red. What happened: the "id": "27" pointed to a credential on the old instance that doesn't exist on the new one. Fragile point 1.
Opening the AI Agent node. Same thing: the "Cumbre OpenAI - Dev" credential isn't there. What happened: the second credential ID, "id": "14", was also left orphaned. The person has to recreate both credentials on the new instance and reassign them by hand.
Looking at the webhook. The webhook's production URL is different from the one it had on the old instance, because the new server has a different domain. What happened: fragile point 3. Even if the person fixes the credentials and the workflow works when run by hand, Cumbre's store keeps sending orders to the old URL. Until someone updates the store to call the new URL, real orders never reach the new workflow.
Running it by hand, after fixing the credentials. It works. And here's the final trap: the person concludes "done, I migrated the workflow," because they watched it run. But real orders still aren't arriving (webhook), and if the new server was meant for testing, the workflow still points to the production CRM (fragile point 4). The workflow "works" in the demo and is broken in reality.
What to expect if you do this migration without a checklist: you're going to fix what's visible (the credentials, because n8n flags them in red) and miss what's invisible (the webhook, the environment values, because nothing flags them). With a risk note in hand —this lesson's list— you deliberately check all four points and no surprises are left.
Why it fails silently (and why that's what makes it dangerous)
It's worth naming head-on the characteristic that makes this problem so costly: almost none of this produces an error at the moment of import.
A loud error —a red screen saying "this is wrong"— is, at bottom, a blessing: it tells you where to look. The reimport problem is that it's silent. The workflow imports "successfully." All the nodes are there. The canvas looks identical. The only signals —the red credential warning— only show up if you open each node to look, and the other problems (webhook, environment values) give no signal at all until a real order fails, days later, far removed from the moment of import.
That gap between the cause (you imported without checking) and the symptom (an order got lost on Thursday) is what makes the problem so hard. When the order fails, nobody thinks "oh, it's that Monday's migration didn't update the webhook"; they think there's a new bug, and they look in the wrong place.
The only defense against a silent failure is proactive verification: don't wait for something to scream, check on purpose, with a list, every point you know breaks. That list is this lesson's product, and it's literally what you're going to write in the module's project. A system owner's discipline isn't "fix it fast when something fails"; it's "verify before it fails, because I know exactly what fails."
What you need to control so it doesn't happen
Let's close with the constructive part: now that you know what breaks, what do you control? This lesson doesn't give you the full solutions yet —they live in Modules 3 and 4— but it does give you the map of what needs solving:
- Credentials kept outside the workflow, and recreated in each environment. Don't depend on the credential ID matching between instances. Each environment (
dev/staging/prod) has its own credentials, and the workflow connects to whichever environment it's running in. This is Module 4. - IDs normalized for versioning. Pin or ignore volatile IDs when versioning, so the diff shows logic instead of identifier noise. This is Module 3.
- Webhooks documented and their rewiring planned. Note down which external systems call each webhook, so that when you move the workflow you know who to notify about the new URL. Part of Module 3's documentation and Module 6's runbook.
- Environment configuration separated from the nodes. The values that change between environments —URLs, thresholds, account identifiers— come out of the nodes and go in as environment configuration, so the same workflow points to testing in
devand to production inprodwithout editing the JSON. This is Module 4.
You'll notice the four solutions are, at bottom, the same idea: separate the workflow from its environment. The JSON describes the "what it does" portably; everything that is "which specific one from this instance" —credentials, addresses, values— lives separately, in environment configuration. When that separation is done well, moving the workflow stops being a minefield. But to do it well, you first had to know exactly what breaks, and now you do.
Common mistakes
Trusting that "it imported fine" because the nodes showed up (practical). What happens: someone imports a workflow, sees all the nodes on the canvas, sees no error, and considers the migration done. Days later something fails in production and nobody connects the failure to the import. Why it happens: the import is silent by design; the absence of an error gets mistaken for the presence of success. How to spot it: if your criterion for "successful migration" is "no red error showed up," you have this problem. How to fix it: adopt proactive verification. After importing, open every node with credentials and confirm it points to a valid credential in the new environment; check the webhook URLs; and run a real test, not just a manual one from the editor. "No error" is not "it works."
Reconfiguring credentials by hand every time, as a method (practical). What happens: someone learns that credentials break when moved, and their solution is "I'll reassign them by hand on every instance." It works once, but doesn't scale: with several workflows, several environments, and several credentials, manual reassignment becomes error-prone work, and forgetting just one is enough to create a silent bug. Why it happens: it's the obvious, short-term solution. How to spot it: if your deployment process includes the step "remember to reassign the credentials," it's fragile. How to fix it: the system owner's solution is structural, not manual: credentials per environment with a predictable identity, so the same workflow finds the right credentials in every environment with no intervention. That's Module 4. Manual reassignment is acceptable as a one-off patch, never as a process.
Forgetting the webhooks because n8n doesn't flag them (practical). What happens: someone fixes the credentials when migrating —because n8n flags them in red— and completely forgets the webhook, because nothing points it out. Real orders stop arriving and the problem takes a while to discover. Why it happens: attention goes where there's a visible signal, and the webhook gives none inside n8n. How to spot it: if you migrated a workflow with a webhook and didn't update the external system calling it, you already have the latent problem. How to fix it: treat the webhook as part of the migration, not as a detail. Note in your portability note which external systems call each webhook and plan to update them to the new URL as part of the deployment.
Believing a test environment is safe just because it's called "test" (conceptual and dangerous). What happens: someone sets up a "test" instance, imports a production workflow into it, and runs it comfortably thinking it can't do harm. But the workflow had the real CRM's URL hand-written into a node, so their "test" wrote to the production CRM. Why it happens: it's assumed that the environment's "test" label changes the workflow's behavior, and it doesn't: the workflow points wherever its JSON says to point, regardless of what the environment is called. How to spot it: before running an imported workflow in a test environment, search its JSON for URLs and credentials pointing to real systems. How to fix it: environment-specific values have to come out of the nodes (Module 4). As long as they're hand-written inside the workflow, "test environment" is just a name, not a guarantee.
Exercises
Exercise 1 — Hunt for the fragile fields. Take order-triage's skeleton from lesson 4 (or your own exported workflow). Make a list of every field that would break or change when imported into another instance, and classify it by fragile point: (1) credential, (2) node ID, (3) webhook, (4) environment variable/value.
See solution
For order-triage's skeleton, the list is:
- Point 1 (credentials):
credentials.id = "27"on the CRM node, andcredentials.id = "14"on the AI Agent node. Two references that would be orphaned. - Point 2 (node IDs): the three node
ids (11111111-...,22222222-...,33333333-...) could get regenerated. They don't break the flow (connections use names), but they clutter the diff and are a minor risk. - Point 3 (webhook): the
webhookIdof the Webhook node and the URL it produces would change with the new instance's domain; the external system calling it needs rewiring. - Point 4 (environment values): the CRM
urlis hand-written intoparameters(https://crm.example.com/...). It travels fine, but it would point to the same CRM regardless of the destination environment —dangerous if the destination was a test one.
Why it works: if you found both credential IDs and the webhook, you've already internalized the two points that break the most. The hand-written URL is the easiest one to overlook because it does not visibly break —it travels perfectly— and yet it's the one that can make a test environment touch real data. That's the trap of point 4.
Exercise 2 — Explain the silent failure. A coworker tells you: "I imported the workflow, no error came up, so it's fine." Write the reply you'd give them, in three or four sentences, explaining why "no error" doesn't mean "it works" in this case, and what they should check.
See solution
One possible reply:
"No error showing up on import doesn't mean it works, because this kind of problem fails silently. Import copies the credential references, not the credentials, so the CRM and AI Agent nodes probably point to credentials that don't exist on this instance —open them and check if the credential field is red. Also, the webhook has a new URL, so even if the workflow runs fine by hand, the system that sends it orders is still calling the old address. Before calling it good, check both credentials, the webhook URL, and run an end-to-end test, not just a manual run."
Why it works: the reply separates the two illusions —"no error came up" and "it ran by hand"— from the reality —"it actually works, end to end." Naming the concrete points (red credentials, webhook URL, end-to-end test) turns a vague warning into an actionable list. That's, in miniature, the project's portability risk note.
Exercise 3 — Design the checklist. Write a five-step checklist you'd follow after importing any workflow with credentials and a webhook into a new instance, before declaring it functional. Order it from most likely to break to least.
See solution
One possible list:
- Open every node with credentials and confirm it points to a valid credential in the new environment (not red, not blank). This is what breaks the most.
- Recreate or reassign the missing credentials on the new environment, verifying they're the correct environment's (test in
dev, not production). - Note the new URL for each webhook and check which external system calls it, to plan the rewiring.
- Review the
parametersfor hard-coded values —URLs, identifiers— that should change per environment but don't automatically. - Run an end-to-end test with test data, not just a manual run from the editor, and confirm the result is what's expected.
Why it works: the order matters. Credentials come first because they break the most and are the only thing n8n flags for you. The webhook and hard-coded values come in the middle because they're silent. The end-to-end test goes last because it's what confirms everything above went well. This list is essentially the procedure that Module 6 formalizes as part of the promotion runbook. Save it: you'll reuse it in lesson 8's project.
Summary and next step
In this lesson you saw why importing a workflow is like moving only the speed-dial labels from an old phone to a new one: the references get copied, the instance's concrete values don't, and the phone doesn't warn you until you press a button. You walked through the four fragile points of a reimport: credential IDs (the one that breaks the most, because they're per instance and order-triage has two), node IDs (which don't usually break the flow but clutter the history and are an occasional source of failures), webhooks (which change URL and break the external systems calling them, with no signal at all inside n8n), and environment variables and values (which either don't travel, or travel too well and make a test environment touch real data). You understood why all of this fails silently —with no big error at the moment of import— and why that gap between cause and symptom is what makes it so costly. And you saw the map of what needs controlling, which boils down to one idea: separate the workflow from its environment, the thesis of Modules 3 and 4.
Before moving on you should be able to: name the four fragile points and which one breaks the most; explain why "it imported without error" doesn't mean "it works"; and describe in one sentence why separating the workflow from its environment fixes the problem at the root.
You now have the problem fully diagnosed: you know what a versioned workflow is (lesson 1), why the market asks for it (lesson 2), why export/import isn't enough (lesson 3), what's inside the JSON (lesson 4), and what breaks when you move it (lesson 5). What's missing is the frame that arranges all these pieces into a single coherent mental model. Lesson 6 gives you that: workflow as code. You're going to see why the repository, and not the n8n instance, is the source of truth; what the work cycle is —edit, export, commit, review, promote— and why thinking of the instance as a "runtime" and the repo as the "source" solves versioning, environments, and testing all at once. It's the lesson that turns five problems into a single model.
Resources
- Export and import workflows — n8n Docs — the official page, with the explicit warning about credential names and IDs in the JSON and about authentication headers in HTTP nodes imported from cURL.
- Credentials — n8n Docs — how n8n manages credentials separately from the workflow; the foundation for understanding why the credential ID is per instance.
- Webhook node — n8n Docs — the Webhook node reference, including the test and production URLs whose change when moving the workflow is fragile point 3.
- Environment variables — n8n Docs — the environment variables a workflow can depend on that don't travel in the JSON; the foundation for fragile point 4 and Module 4.
- CLI commands — n8n Docs — the command-line interface for exporting and importing, which gives you more control than the editor over how IDs are handled; you use it in depth in Module 3.