n8n-io/n8n · error · UserError
Workflow "${workflowId}" not found.
Error message
Workflow "${workflowId}" not found. What it means
UserError thrown by WorkflowRepository.updateActiveState() when no workflow exists with the given workflowId (checked via existsBy). The method flips active/activeVersionId; refusing on a missing workflow prevents writing a phantom update. Distinct from the publishVersion not-found at line 1528.
Source
Thrown at packages/@n8n/db/src/repositories/workflow.repository.ts:1499
async findIn(workflowIds: string[]) {
return await this.find({
select: ['id', 'name'],
where: { id: In(workflowIds) },
});
}
async findWebhookBasedActiveWorkflows() {
return await (this.createQueryBuilder('workflow')
.select('DISTINCT workflow.id, workflow.name')
.innerJoin(WebhookEntity, 'webhook_entity', 'workflow.id = webhook_entity.workflowId')
.execute() as Promise<Array<{ id: string; name: string }>>);
}
async updateActiveState(workflowId: string, newState: boolean) {
const wfExists = await this.existsBy({ id: workflowId });
if (!wfExists) {
throw new UserError(`Workflow "${workflowId}" not found.`);
}
if (newState) {
return await this.createQueryBuilder()
.update(WorkflowEntity)
.set({
activeVersionId: () => 'versionId',
active: true,
})
.where('id = :workflowId', { workflowId })
.execute();
} else {
return await this.update({ id: workflowId }, { active: false, activeVersionId: null });
}
}
/**
* Publish a specific version of a workflowView on GitHub (pinned to 5ac6606e81)
Solutions
- Confirm the workflow exists before toggling: `await workflowRepo.existsBy({ id })`.
- If the workflow may have been deleted, treat 404 as a normal result and clean up dependent webhooks/triggers.
- Validate the ID format upstream (UUID) to fail fast with a clearer message.
- For background re-activation jobs, skip rather than throw on missing IDs.
Example fix
// before
await workflowRepo.updateActiveState(workflowId, true);
// after
if (!(await workflowRepo.existsBy({ id: workflowId }))) {
return { status: 'not_found', workflowId };
}
await workflowRepo.updateActiveState(workflowId, true); Defensive patterns
Strategy: validation
Validate before calling
if (!(await workflowRepository.existsBy({ id: workflowId }))) {
// do not call updateActiveState; return not_found
} Type guard
async function workflowIsActive(id: string): Promise<boolean> {
return await workflowRepository.existsBy({ id });
} Try / catch
try {
await workflowRepository.updateActiveState(workflowId, state);
} catch (err) {
if (err instanceof UserError && /Workflow .* not found/.test(err.message)) {
// 404, and clean up dependent webhooks/triggers
} else throw err;
} Prevention
- Existence-check before toggling active state.
- Handle stale IDs gracefully in background re-activation jobs (skip, don't throw).
- Validate UUID format upstream.
When it happens
Trigger: Calling updateActiveState(id, bool) with an id that was deleted, never existed, or is malformed (not a UUID). Common in activation/deactivation flows, webhooks, and the active toggle API.
Common situations: UI 'activate' click racing with a delete; an API call with a stale workflow ID; a webhook re-activation job referencing a removed workflow; copy-paste ID typos; trying to activate an archived workflow via the wrong path.
Related errors
- Failed to find workflow with ID "${workflowId}"
- Role not found
- Cannot publish archived Workflow
- Version "${versionIdToPublish}" not found for workflow "${wo
- Workflow ${formatWorkflow(dbWorkflow)} has no node to start
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/96cd5d66f360f5e4.
Report an issue: GitHub.