Upgrading n8n broke my instance

It will not start after the pull, or it starts and behaves differently. Also why going back is harder than it looks, and what to do before the next one.

What you are seeing

n8n will not start after an upgrade, and the logs mention a database migration.

It starts, but nodes behave differently, or a workflow that ran yesterday now fails on a step you did not touch.

You tried to go back to the old version and it will not start either, which is the part nobody expects.

Why it happens

The version was never pinned

If you are following the latest tag, then every pull is an upgrade to whatever shipped since, possibly across a major version, at a moment you chose for unrelated reasons. Most of the time this is fine, and the time it is not, it is a surprise.

Migrations run on start and they only run forwards

When a new version needs a different database shape, it changes your database on the way up, automatically. That is why the upgrade is quick and why going back is not: the old version now sees a database from the future and refuses it.

This is the single most important thing to understand about n8n upgrades. Downgrading is not undoing the upgrade. It is restoring a backup taken before it, and if there is no backup, there is no going back.

How to fix it

Read the actual error first

Migration failures usually name the step that failed and the reason. It is frequently something boring like the database user lacking permission to alter a table, or the disk being full at the wrong moment, and both of those are fixable in place.

docker compose logs --tail=200 n8n

If you have a backup, this is a five minute job

Stop n8n, restore the database from before the upgrade, pin the image back to the exact version you were running, start. Keep the same encryption key, or the restore comes back with credentials nobody can read.

docker compose down
# restore the database dump you took before upgrading
# then pin the version you were on and bring it back up
docker compose up -d

If you do not have a backup

Go forward rather than back. Fix the migration error if it names something fixable. If the new version starts but a workflow misbehaves, read the release notes between your old version and this one and look for the node you are using, because breaking changes are listed and the fix is usually a setting.

The last resort, if the instance still runs at all, is to export your workflows, stand up a clean instance on the version you want, and import them. It is slow but it works, and it is another argument for exporting on a schedule.

Stopping it happening again

Pin the version. This is the whole lesson.

Name an exact version in the image tag. Then an upgrade is something you decided to do on a Tuesday morning, not something that happened while you were restarting for another reason.

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:1.70.0   # not :latest, ever

Back up first, every time, and move one step at a time

Dump the database and copy the encryption key before you change the tag. Ninety seconds of work that converts a bad day into a five minute rollback.

Move one major version at a time and read what changed. Skipping four versions at once means four sets of breaking changes arriving together with nothing to tell you which one broke you.

The other ways this goes wrong

The setup that avoids most of them, written out in full