invoke-ai/InvokeAI · error

Default workflows cannot be updated

Error message

Default workflows cannot be updated

What it means

update() refuses to modify workflows whose meta.category is WorkflowCategory.Default. Default workflows shipped with the application are treated as immutable through the public API to keep them in sync with app releases.

Source

Thrown at invokeai/app/services/workflow_records/workflow_records_sqlite.py:78

        with self._db.transaction() as cursor:
            workflow_with_id = Workflow(**workflow.model_dump(), id=uuid_string())
            cursor.execute(
                """--sql
                INSERT OR IGNORE INTO workflow_library (
                    workflow_id,
                    workflow,
                    user_id,
                    is_public
                )
                VALUES (?, ?, ?, ?);
                """,
                (workflow_with_id.id, workflow_with_id.model_dump_json(), user_id, is_public),
            )
        return self.get(workflow_with_id.id)

    def update(self, workflow: Workflow, user_id: Optional[str] = None) -> WorkflowRecordDTO:
        if workflow.meta.category is WorkflowCategory.Default:
            raise ValueError("Default workflows cannot be updated")

        with self._db.transaction() as cursor:
            if user_id is not None:
                cursor.execute(
                    """--sql
                    UPDATE workflow_library
                    SET workflow = ?
                    WHERE workflow_id = ? AND category = 'user' AND user_id = ?;
                    """,
                    (workflow.model_dump_json(), workflow.id, user_id),
                )
            else:
                cursor.execute(
                    """--sql
                    UPDATE workflow_library
                    SET workflow = ?
                    WHERE workflow_id = ? AND category = 'user';
                    """,

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Duplicate the workflow as a Custom-category copy and update that instead
  2. Skip Default-category workflows in update loops (filter on workflow.meta.category)
  3. If a shipped default truly needs changes, update it via the app's default-workflow sync mechanism, not update()

Example fix

// before
for wf in all_workflows:
    service.update(wf)
// after
for wf in all_workflows:
    if wf.meta.category is not WorkflowCategory.Default:
        service.update(wf)
Defensive patterns

Strategy: validation

Validate before calling

if workflow.meta.category is WorkflowCategory.Default:
    raise SkipUpdate(f"{workflow.id} is a default workflow; duplicate it first")

Type guard

def is_custom(workflow: Workflow) -> bool:
    return workflow.meta.category is not WorkflowCategory.Default

Try / catch

try:
    record = service.update(workflow)
except ValueError as e:
    if "Default workflows cannot be updated" in str(e):
        record = duplicate_as_custom(service, workflow)  # create Custom copy, edit that
    else:
        raise

Prevention

When it happens

Trigger: Calling update(workflow) where workflow.meta.category is Default; loading a default workflow in the editor and saving it back unchanged in category.

Common situations: Bulk edit scripts iterating all workflows without filtering category; user duplicating-but-not-actually-copying a default workflow (same id/category); migrations that touch every row.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/8a31cf597458e309. Report an issue: GitHub.