n8n-io/n8n · error · UserError

Down migration only possible when there are no projects. Ple

Error message

Down migration only possible when there are no projects. Please delete all projects that were created via the UI first.

What it means

UserError thrown by CreateProject migration 1714133768519.down() if any non-personal projects exist when the user attempts to roll back. The down migration can only revert when only personal projects remain, because shared/project workflows created via the UI cannot be safely unmigrated. Logged at error level before throwing.

Source

Thrown at packages/@n8n/db/src/migrations/common/1714133768519-CreateProject.ts:246

		await this.alterSharedTable(table.sharedCredentials, context);
		await this.alterSharedCredentials(context);
		await this.alterSharedTable(table.sharedWorkflow, context);
		await this.alterSharedWorkflow(context);
	}

	async down({ logger, escape, runQuery, schemaBuilder: sb }: MigrationContext) {
		const { t, c } = escapeNames(escape);

		// 0. check if all projects are personal projects
		const [{ count: nonPersonalProjects }] = await runQuery<[{ count: number }]>(
			`SELECT COUNT(*) FROM ${t.project} WHERE type <> 'personal';`,
		);

		if (nonPersonalProjects > 0) {
			const message =
				'Down migration only possible when there are no projects. Please delete all projects that were created via the UI first.';
			logger.error(message);
			throw new UserError(message);
		}

		// 1. create temp table for shared workflows
		await sb
			.createTable(table.sharedWorkflowTemp)
			.withColumns(
				sb.column('workflowId').varchar(36).notNull.primary,
				sb.column('userId').uuid.notNull.primary,
				sb.column('role').text.notNull,
			)
			.withForeignKey('workflowId', {
				tableName: 'workflow_entity',
				columnName: 'id',
				onDelete: 'CASCADE',
				name: undefined,
			})
			.withForeignKey('userId', {
				tableName: table.user,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Before reverting, delete all non-personal (team/community) projects via the n8n UI so only personal projects remain.
  2. If reverting is impossible, restore from a pre-migration backup instead of running the down migration.
  3. Document that this migration is effectively irreversible once shared projects exist — plan upgrades accordingly.
  4. For dev environments, wipe the DB and re-seed rather than reverting.

Example fix

// before
n8n migration:revert --all

// after
# 1. in the n8n UI, delete every team/community project
# 2. confirm only personal projects remain, then
n8n migration:revert
Defensive patterns

Strategy: validation

Validate before calling

const nonPersonal = await runQuery(`SELECT COUNT(*) FROM project WHERE type <> 'personal';`);
if (nonPersonal > 0) {
  // do not attempt the down migration; clean up or restore instead
}

Try / catch

try {
  await migrationRevert();
} catch (err) {
  if (err instanceof UserError && /Down migration only possible when there are no projects/.test(err.message)) {
    // surface: delete non-personal projects first, or restore from backup
  } else throw err;
}

Prevention

When it happens

Trigger: Running `n8n migration:revert` (or a down migration tool) on a DB where users have created non-personal projects (team/community projects). The check counts rows in the project table with type <> 'personal' and refuses if > 0.

Common situations: Attempting to downgrade n8n across the project-acl boundary after users adopted shared projects; rolling back a failed upgrade without first cleaning up team projects; restoring an upgraded DB and trying to revert.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/3db8304e58265fe3. Report an issue: GitHub.