n8n18 min readPublished September 2026

Autosave failed, database is locked: the n8n errors that are not in your workflow

Four self-hosted failures from one month of the n8n forum, and none of them was caused by the workflow the message pointed at. A save rejected before it reached n8n, a database file locked with nothing writing to it, a duplicate that cannot be deleted, and a queue that keeps reconnecting.

The message and the cause are in different layers

An n8n error normally tells you where to look. A node turns red, the input and output are right there, and the fix is in the workflow.

The failures in this article do not work like that. They are produced by the layers underneath the canvas - the database file, whatever sits in front of the container, and the queue broker beside it - and every one of them arrives dressed as an editor problem. Four threads from the n8n community over the past month, each one a different layer, each one debugged for days in the wrong place.

If you host n8n yourself, this is the class of problem that eats the afternoon. n8n is blunt about the trade in its own installation docs:

Self-hosting n8n requires technical knowledge... n8n recommends self-hosting for expert users. Mistakes can lead to data loss, security issues, and downtime.

"Workflow was changed by someone else", and nobody else is here

The first one is the most disorienting, because the interface accuses a colleague who does not exist:

Whenever I edit a workflow with postgres nodes in it, I am met with errors saying "Problem saving workflow Autosave failed: Can't connect to n8n. Retrying in 2s..." and "Workflow was changed by someone else Someone saved this workflow while you were editing it. You can view their version (in new tab). Overwrite their changes with yours?". I know for a fact I am the only one working on these workflows and that the workflows are only ever opened in one browser/tab.

The thread ran for a week. Upgrading did not fix it. Rebuilding the workflow from scratch reproduced it as soon as the same node was added back. What finally produced a usable clue was opening the browser's network tab during an autosave:

I opened the developer tools and saw a 409 conflict error in the network panel while editing the workflow.

  • the same user, same thread, 7 August 2026

A 409 means the request reached n8n and was refused as a conflict, which is a different investigation from "can't connect to n8n" - the message the editor had been showing for days. The thread has no accepted resolution, so take the method rather than the diagnosis: the popup named a person, and what the server actually returned was a conflict status.

Whenever an n8n save fails, the useful information is in the browser network tab, not in the popup. Open devtools, reproduce the failure, and read the status code on the save request. 403, 409 and a timeout are three different investigations, and the popup wording does not distinguish them.

"Autosave failed: Request failed with status code 403"

Same popup family, completely different cause. A user building an AI agent on a corporate instance:

The issue is that for some reason, halfway through building it, I always get this error "Problem saving workflow Request failed with status code 403". Ive tried logging out and in, clearing cookies, trying another browser, download the the workflow and importing it into a new one, rebuilding the exact same workflow, it always runs into the same issue. The error randomly shows up, it doesnt seem to be depending on a specific node... A lot of times, writing system message creates the error.

Everything in that list is an n8n-side remedy, and none of them worked, because the save was never reaching n8n. Two details from the thread point at the layer in front: it fails more often as the workflow gets bigger, and it fires when typing prose into a system message.

The forum's working theory was a web application firewall, and the numbers behind that theory are published by AWS. The core rule set that most teams switch on contains a rule called SizeRestrictions_BODY, described in one line:

Inspects for request bodies that are over 8 KB (8,192 bytes).

Rule action: Block

Eight kilobytes is a small workflow. And the same document explains why a bigger inspection limit is not always available:

For Application Load Balancer and AWS AppSync, the limit is fixed at 8 KB. For CloudFront, API Gateway, Amazon Cognito, App Runner, Verified Access, and Amazon Bedrock AgentCore Gateway, the default limit is 16 KB and you can increase the limit up to 64 KB in your protection pack (web ACL) configuration.

The same rule group also contains CrossSiteScripting_BODY, which inspects request bodies for XSS patterns - which is a plausible reason a save fails specifically while somebody types instructions containing angle brackets or a URL into an agent's system message.

An editor error that depends on how much you typed is not an editor error. It is something between your browser and n8n reading the request and deciding it does not like the size of it.

Nothing here is proven for that particular user's instance - the thread ends with n8n opening an internal ticket and the reporter going to ask whoever owns the AWS account. But the shape is worth recognising, because it is un-debuggable from inside n8n: if a proxy or WAF blocks the save, n8n has no log line for a request it never received, and every experiment you run in the editor will look random.

"Database is locked" with nothing writing to it

The third layer down is the database file itself. An agency running two clients on one instance spent a day trying to take a backup:

Started simple: sqlite3 database.sqlite ".backup 'out.sqlite'". Straight up Error: database is locked, first try.

Timeouts of 10, 30 and 60 seconds did not help. A retry loop for six to eight minutes did not help. Deactivating all 40 active workflows through the API did not help. Pausing the entire container did not help either, which is the detail that rules out "something is busy writing":

Last thing I tried, kind of out of ideas at that point is docker pause'd the whole container and tried .backup while it was completely frozen. Failed instantly, before I even unpaused.

  • the same user, same thread, 16 August 2026

A day later the same person found a stale journal file next to the database, 58 MB, last modified hours behind the live file - the fingerprint of a transaction that was interrupted rather than of a writer that is still working.

What eventually produced a verified backup was to stop asking SQLite anything at all:

What actually works: docker pause, then a plain cp -a of the whole data directory (not .backup, not sqlite3 at all), then docker unpause. Plain cp doesn't ask SQLite for anything, it just reads bytes off disk, so it never hits the lock in the first place.

  • the same user, same thread, 17 August 2026

Two things make that report worth more than the usual forum answer. First, it was tested as a restore, not as a file: the snapshot was mounted into a throwaway container on another machine, logged Last session crashed, ran its recovery on startup and came up with the full workflow list. Second, the freeze window was measured - a bit over two minutes for a 3.5 GB data directory - and requests hitting a paused container queue instead of being refused, which is gentler than deactivating workflows (that returns "webhook not registered" immediately).

A backup you have never restored is not a backup. That is the transferable part of the thread, and it is worth an hour of your own time on any instance holding client work.

The default database is the less reliable one, and n8n says so

Underneath that story is a setting most self-hosted instances never touch. n8n's own environment variable reference:

DB_SQLITE_POOL_SIZE has a documented default of 0, and the description of what that means is worth reading to the end:

Controls whether to open the SQLite file in WAL mode or rollback journal mode. Uses rollback journal mode when set to zero. When greater than zero, uses WAL mode with the value determining the number of parallel SQL read connections to configure. WAL mode is much more performant and reliable than the rollback journal mode.

Read the default and the last sentence together. Out of the box you get the mode n8n describes as less performant and less reliable, and switching is one environment variable. In WAL mode a reader does not queue behind the writer, which is precisely the backup problem above.

n8n has said it intends to remove the old driver entirely:

n8n will remove the legacy SQLite driver due to reliability issues. The pooling driver will become the default and only SQLite driver. The pooling driver uses WAL mode, a single write connection, and a pool of read connections. Our benchmarks show it can be up to 10 times faster.

Migration path: The sqlite-pooled driver will become the default automatically. You can enable pooling now by setting DB_SQLITE_POOL_SIZE to a value greater than 0. The default pool size will be set to 2.

Two cautions before you plan around that. The breaking-changes page is written in the future tense while the current stable release is 2.36.x, and the environment variable reference still prints a default of 0 today - so check the value your own instance is actually running rather than assuming the migration has reached you. And the v3.0 breaking-changes page, for the October 2026 release, does not mention the database at all.

This is not only a self-hosting problem

It is tempting to file all of this under "that is what you get for self-hosting". The database page says otherwise:

n8n Cloud installations use different databases depending on your plan tier:

SQLite: Starter, Pro, and legacy Enterprise plans

PostgreSQL: Enterprise Scaling plans only

Which is why a Cloud user hit a database-level error with no server to log into:

When duplicating an existing workflow that contains a Trello Trigger node, n8n retains the original workflow's hidden webhook and credential references in the database. Even after changing the credentials and updating the Trello node parameters in the duplicated workflow, n8n keeps throwing a credential error pointing to the deleted original credential ID

The suggested fix - delete the trigger node, drag in a fresh one so it gets a new webhookId, reattach the credential - did not work for this reporter. The workflow ended up in a state where it could not be saved and could not be deleted either:

Once the workflow entered this state, deleting the nodes completely and leaving a totally empty canvas still produced the SQLITE_CONSTRAINT: FOREIGN KEY constraint failed error when trying to delete the workflow itself. The only workaround that worked for me was leaving the broken duplicated workflow behind and recreating the entire workflow manually from scratch on a completely new canvas.

  • the same user, same thread, 11 August 2026

An n8n team member was still working the case in the thread on 17 August. The practical lesson stands whatever the resolution: duplicating a workflow that contains a trigger with a registered webhook is not the same as building a copy of it, and if a duplicate starts producing credential errors that name an ID you have already deleted, rebuilding is cheaper than fighting it. That is a different failure from the editor showing you one version while production runs another, which has its own causes and its own fix.

"Lost Redis connection... Recovered Redis connection"

The last layer only exists if you run queue mode, and its signature is a log that looks alarming and repairs itself:

2026-08-11T12:50:34.114Z | warn | Lost Redis connection. Trying to reconnect in 1s... (0s/60s)

2026-08-11T12:50:35.157Z | info | Recovered Redis connection

The user checked Redis from a separate pod with a ping loop every two seconds and saw a perfect run of PONG. The accepted answer explains why that test proves nothing: a ping every two seconds never lets the connection go idle, while the queue holds blocking and pub/sub sockets that sit idle for minutes.

If your broker is managed, the timeout is published. Aiven's troubleshooting page for Aiven for Valkey states that it "sets the valkey_timeout advanced parameter to 300 seconds by default", and that this parameter "controls the timeout value for idle connections. Once the timeout is reached, the connection is terminated." The same page adds a second behaviour you cannot configure away: its SSL connections "are closed automatically after 12 hours. This is not a parameter that can be changed."

The reason to fix a warning that recovers on its own is in n8n's queue settings. A worker holds a lease on the job it is running:

VariableDefaultWhat n8n documents
QUEUE_WORKER_LOCK_DURATION60000"How long (in ms) is the lease period for a worker to work on a message"
QUEUE_WORKER_LOCK_RENEW_TIME10000"How frequently (in ms) should a worker renew the lease time"
QUEUE_WORKER_STALLED_INTERVAL30000"How often should a worker check for stalled jobs (use 0 for never)"
QUEUE_WORKER_MAX_STALLED_COUNT1"Maximum amount of times a stalled job will be re-processed"

A dropped connection at the wrong moment means a lease that does not get renewed, a job that counts as stalled, and a default that allows it to be re-processed once. For an execution that writes to a customer's system, "re-processed" is a word worth sitting with - it is the same territory as an automation that runs twice.

Before
  • Saves fail intermittently and the popup blames a colleague who does not exist
  • Backups are a cron job copying a file nobody has ever restored
  • The database is on whatever mode the container started with, unexamined
  • Redis warnings are ignored because the next line always says recovered
After
  • Failed saves are diagnosed by status code in the network tab: 403 is infrastructure, 409 is versioning
  • The backup procedure has been restored into a throwaway instance at least once, and the restore is what is documented
  • DB_SQLITE_POOL_SIZE is a deliberate decision, and heavy multi-client instances are on PostgreSQL
  • Broker idle timeouts are set above the queue's idle gaps, and stalled-job settings are known rather than default

What we would check on a self-hosted instance

  • Reproduce any failing save with devtools open and record the status code: 403 means something in front of n8n rejected it, 409 means a version conflict, a timeout means the connection
  • If saves fail more often as workflows grow, ask whoever owns the proxy or WAF about request body inspection limits, starting at 8 KB
  • Check DB_SQLITE_POOL_SIZE on the running instance rather than assuming, and treat rollback journal mode as a choice you are making
  • Restore a backup into a throwaway container on another machine, and time it, before you need it
  • Prefer a snapshot method that does not go through SQLite locking, such as pausing the container and copying the data directory
  • Move multi-client production instances to PostgreSQL rather than growing a multi-gigabyte SQLite file
  • Treat a duplicated workflow containing a webhook trigger as suspect: verify the new webhook URL differs from the original before activating
  • On queue mode, set the broker's idle timeout above your longest idle gap, and read your stalled-job settings before assuming a lost connection is harmless

None of these four problems was in a workflow. Each one was a layer that the editor cannot see, reporting through a message that sounds like it can. The habit that shortens all of them is the same: when n8n tells you something about your workflow that you know is false, stop treating the message as evidence and go one layer down.

Sources

  • Corrupted Workflows Related to Postgres Nodes - n8n Community, thread opened 30 July 2026, read 25 August 2026. The autosave and "changed by someone else" messages with a single editor, the upgrade and rebuild both failing to help, and the 409 conflict observed in the network panel on 7 August. The thread has no accepted resolution.
  • Problem saving workflow Autosave failed: Request failed with status code 403 - n8n Community, thread opened 9 August 2026, read 25 August 2026. The 403 that survived new browsers and cleared cookies, its correlation with workflow size and with typing a system message, and n8n's reply that an internal ticket was created. The firewall explanation in that thread is a community hypothesis, not a confirmed diagnosis.
  • SQLite stays permanently locked (SQLITE_BUSY) even with all workflows deactivated and the container fully paused - n8n Community, thread opened 16 August 2026, read 25 August 2026. The failed .backup attempts with timeouts and retries, deactivating 40 workflows, the paused container still failing, the stale 58 MB journal file, and the accepted answer of pause plus cp plus unpause, verified by restoring into a throwaway container that logged "Last session crashed" and recovered.
  • Duplicating workflow with Trello/Webhook trigger retains ghost credential IDs and causes SQLITE_CONSTRAINT error - n8n Community, thread opened 5 August 2026, read 25 August 2026. The duplicate retaining hidden webhook and credential references, the credential error naming a deleted ID, the FOREIGN KEY constraint failure when deleting the workflow, the fresh-trigger-node fix not working for this reporter, and the rebuild-from-scratch workaround. The reporter is on n8n Cloud.
  • REDIS Lost / Recovered only inside n8n - n8n Community, thread opened 11 August 2026, read 25 August 2026. The repeating lost and recovered log lines, the ping loop that showed a healthy connection, and the accepted answer explaining that a two-second ping never lets the connection go idle while queue sockets do.
  • Database environment variables - n8n Docs, read 25 August 2026. DB_SQLITE_POOL_SIZE defaulting to 0, rollback journal mode at zero, WAL mode above zero, and WAL being "much more performant and reliable than the rollback journal mode". Also the queue and recovery defaults quoted elsewhere on this page.
  • Queue mode environment variables - n8n Docs, read 25 August 2026. QUEUE_WORKER_LOCK_DURATION, QUEUE_WORKER_LOCK_RENEW_TIME, QUEUE_WORKER_STALLED_INTERVAL and QUEUE_WORKER_MAX_STALLED_COUNT with their defaults and descriptions.
  • v2.0 Breaking changes - n8n Docs, read 25 August 2026. The legacy SQLite driver being removed "due to reliability issues", the pooling driver becoming default with WAL mode and a pool size of 2, and the instruction to enable pooling now by setting DB_SQLITE_POOL_SIZE above 0. Written in the future tense; the current stable release at the time of reading was 2.36.6.
  • v3.0 Breaking changes - n8n Docs, read 25 August 2026. Checked for database changes in the October 2026 release: the page covers Docker-only deployment and removed nodes, and does not mention SQLite.
  • Choose n8n's database - n8n Docs, read 25 August 2026. SQLite as the default for self-hosted installations, and n8n Cloud running SQLite on Starter, Pro and legacy Enterprise plans with PostgreSQL only on Enterprise Scaling.
  • Install with Docker - n8n Docs, read 25 August 2026. The self-hosting knowledge prerequisites and the warning that mistakes can lead to data loss, security issues, and downtime, plus the current stable version number.
  • Baseline rule groups - AWS WAF Developer Guide, read 25 August 2026. The SizeRestrictions_BODY rule blocking request bodies over 8 KB (8,192 bytes), the CrossSiteScripting_BODY rule in the same core rule set, and the per-resource body inspection limits: fixed at 8 KB for Application Load Balancer and AWS AppSync, 16 KB by default elsewhere with up to 64 KB configurable.
  • Troubleshoot Aiven for Valkey connection issues - Aiven documentation, read 25 August 2026. The valkey_timeout advanced parameter set to 300 seconds by default, that parameter controlling the timeout for idle connections, and SSL connections being closed automatically after 12 hours with no parameter to change it.

Broken workflow? Fix S — $300, 2 business days, fixed price.

Get my quote in 24h

Written by the Fixmation team.