n8n-io/n8n · error · UserError

Cannot publish archived Workflow

Error message

Cannot publish archived Workflow

What it means

UserError thrown by WorkflowRepository.publishVersion() when the workflow exists but has isArchived === true. Archived workflows are immutable and cannot be published; the error includes extra.{workflowId} for telemetry/debugging. Fires after the not-found check, before version lookup.

Source

Thrown at packages/@n8n/db/src/repositories/workflow.repository.ts:1532

	}

	/**
	 * Publish a specific version of a workflow
	 * @param workflowId - The ID of the workflow
	 * @param versionId - The ID of the version to publish (optional; if not provided, uses the current version)
	 * */
	async publishVersion(workflowId: string, versionId?: string) {
		const workflow = await this.findOne({
			where: { id: workflowId },
			select: ['id', 'versionId', 'isArchived'],
		});

		if (!workflow) {
			throw new UserError(`Workflow "${workflowId}" not found.`);
		}

		if (workflow.isArchived) {
			throw new UserError('Cannot publish archived Workflow', {
				extra: { workflowId },
			});
		}

		const versionIdToPublish = versionId ?? workflow.versionId;

		const version = await this.workflowHistoryRepository.findOneBy({
			workflowId,
			versionId: versionIdToPublish,
		});
		if (!version) {
			throw new UserError(
				`Version "${versionIdToPublish}" not found for workflow "${workflowId}".`,
			);
		}

		return await this.update(
			{ id: workflowId },

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Unarchive the workflow first, then publish: `await workflowRepo.update({ id }, { isArchived: false })`.
  2. Filter archived workflows out of any bulk-publish job.
  3. Surface a UI hint: 'This workflow is archived. Restore it before publishing a version.'
  4. If archival was intentional and permanent, treat publish as an invalid action and do not expose the button.

Example fix

// before
await workflowRepo.publishVersion(archivedId, versionId);

// after
await workflowRepo.update({ id: archivedId }, { isArchived: false });
await workflowRepo.publishVersion(archivedId, versionId);
Defensive patterns

Strategy: validation

Validate before calling

const wf = await workflowRepository.findOne({ where: { id: workflowId }, select: ['id', 'isArchived'] });
if (!wf) { /* not found */ }
if (wf.isArchived) { // unarchive first, or refuse to publish }

Type guard

function isPublishable(wf: { isArchived: boolean } | null): wf is { isArchived: false } {
  return wf !== null && wf.isArchived === false;
}

Try / catch

try {
  await workflowRepository.publishVersion(workflowId, versionId);
} catch (err) {
  if (err instanceof UserError && /Cannot publish archived Workflow/.test(err.message)) {
    // unarchive, then retry — or surface to user
  } else throw err;
}

Prevention

When it happens

Trigger: Calling publishVersion on a workflow that was archived (soft-deleted out of the active set). The publish path refuses to promote a version of an archived workflow.

Common situations: A user opens an archived workflow from history/deep link and clicks publish; automation that re-publishes from a list without filtering archived; unarchiving not done before publish.

Related errors


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