Fix n8n 'Published, Has Changes' Workflow Not Going Live
Quick answer
Click Publish and wait until the button reads “Published, up to date”. Until then, production runs the previously published version, not your latest edits.
What broke, and why
You edited a workflow, tested it manually, and everything worked. But in production, the old behavior continues: the schedule fires the old logic and the webhook answers the old way. Nothing is broken in the usual sense. Your edits simply never went live.
In n8n 2.x, saving and publishing are two separate steps. The official save and publish documentation states that changes autosave as you edit, typically within 1 to 5 seconds, and that all edits remain in draft until you publish. Production executions use the published version, not your latest edits. “Published, has changes” means the workflow is published, but you have made changes since the last publish that have not gone live yet.
That explains the most confusing symptom: manual runs work, production runs do not. A manual run tests your draft, while a scheduled run, webhook call, or app event runs the published version. When the two differ, the draft always looks correct by hand.
There is a sneakier variant. Publishing is asynchronous: n8n applies only the triggers that changed, in the background. If one trigger fails to activate, for example because a connected app was unavailable, n8n reports “Published, partial”, and the workflow keeps running the triggers that did activate. If none activate, you get “Failed to publish”, and the workflow is not running at all, even though the published version stays set.
The fix
Do not keep editing and re-testing manually.
- Open the workflow and read the Publish button. If it says “Published, has changes”, click Publish (or press Shift + P), optionally name the version, and click Publish again in the modal.
- Wait for the button to move from Publishing to “Published, up to date” while n8n registers your triggers in the background.
- If the button settles on “Published, partial”, hover over it to see which triggers failed. Fix the underlying problem for each failed trigger, usually reconnecting the app or refreshing an expired credential, then publish again to retry those triggers.
- If the button settles on “Failed to publish”, fix the trigger problem first, then publish again. The published version stays set, so republishing is a retry, not a rebuild.
- If the button shows “Published, error”, fix the errors in your recent changes before you try to publish again.
If you use version history, you can also publish another version from there, which is useful when you want to roll production back to an earlier version rather than forward to the latest draft.
Pitfalls that make the fix look like it failed
First, do not mistake a reload for a failure. Because n8n stores the publish state on the server, reloading the page during a publish still shows Publishing until the result arrives. Wait for one attempt to settle before clicking again.
Second, check whether you are actually allowed to edit. Only one person can edit at a time; if someone else is editing, you see read-only mode and your changes are not saved. If Publish never becomes active, suspect an edit lock.
Third, an open workflow review blocks publishing entirely. If workflow reviews are enabled on your instance and a review is open for this workflow, n8n blocks publishing until the review resolves.
Fourth, watch for the partial-publish trap. After a “Published, partial” result, the triggers that succeeded are live, so a quick test of one path can look fine while another trigger is still stale. Always hover over the button and confirm no failed triggers remain.
One exception: settings-only changes re-publish automatically. Node logic, trigger configuration, and connections all need an explicit publish.
How to verify the fix worked
Check the button first: it must read “Published, up to date”, with no “has changes”, “partial”, or “error” qualifier. Then prove it in production: trigger a real event, wait for the next scheduled run, or call the production webhook URL, not the test URL. Then open the Executions view and confirm a production execution ran with the new behavior, for example the new node output or the new branch taken. A successful manual run in the editor proves nothing here; only a production execution proves the published version changed.
For related failures, see our n8n error handling guide and the n8n 3.0 upgrade guide. If your workflow still misbehaves after the button reads “Published, up to date” and a production execution shows the new version, the problem is in the workflow logic itself, not in publishing.
When this article does not apply
This article does not apply if the workflow was never published in the first place. A button that simply offers Publish on a brand-new workflow is the normal starting state, not a bug; publish it once and production starts. It also does not apply if you unpublished the workflow on purpose, or if you are running a pre-2.x n8n version that still uses the old Active toggle instead of the Publish button. In that older model, the fix is flipping the workflow Active, not publishing. And if production executions already show the new version but produce wrong results, stop chasing publish state and debug the workflow logic instead.
Frequently asked questions
Why does my workflow work when I run it manually but not in production?
A manual run in the editor tests your latest draft, while production executions run the last published version. If the Publish button says 'Published, has changes', your edits exist only as a draft, so production keeps running the old version until you publish.
I clicked Publish, but the button still says Publishing. Did it fail?
Not necessarily. Publishing is asynchronous, and n8n stores the state on the server, so reloading the page still shows Publishing until n8n confirms the result. Wait for the button to settle on 'Published, up to date', 'Published, partial', or 'Failed to publish' before acting.
What should I do when the button says 'Published, partial'?
Hover over the button to see which triggers failed to activate, fix the underlying problem (usually a disconnected app or an expired credential), then publish again to retry just those triggers. The triggers that did activate keep running in the meantime.