langgenius/dify · error
{str(e)}
Error message
{str(e)} What it means
Flask `abort(400, description=str(e))` (HTTP 400) at api/controllers/console/app/workflow.py:1638 in the workflow DELETE handler. It catches `WorkflowInUseError` (a ValueError subclass from services/errors/workflow_service.py) raised by `WorkflowService.delete_workflow` when the target workflow is still referenced by an app and cannot be removed. The 400 description carries the exception message.
Source
Thrown at api/controllers/console/app/workflow.py:1638
@edit_permission_required
@rbac_permission_required(RBACResourceScope.APP, RBACPermission.APP_EDIT)
@console_ns.response(204, "Workflow deleted successfully")
def delete(self, app_model: App, workflow_id: str):
"""
Delete workflow
"""
workflow_service = WorkflowService()
workflow_ref = WorkflowRefService.create_app_workflow_ref(app_model, workflow_id)
# Create a session and manage the transaction
with sessionmaker(db.engine).begin() as session:
try:
workflow_service.delete_workflow(
session=session,
workflow_ref=workflow_ref,
)
except WorkflowInUseError as e:
abort(400, description=str(e))
except DraftWorkflowDeletionError as e:
abort(400, description=str(e))
except ValueError as e:
raise NotFound(str(e))
return None, 204
@console_ns.route("/apps/<uuid:app_id>/workflows/draft/nodes/<string:node_id>/last-run")
class DraftWorkflowNodeLastRunApi(Resource):
@console_ns.doc("get_draft_workflow_node_last_run")
@console_ns.doc(description="Get last run result for draft workflow node")
@console_ns.doc(params={"app_id": "Application ID", "node_id": "Node ID"})
@console_ns.response(
200,
"Node last run retrieved successfully",
console_ns.models[WorkflowRunNodeExecutionResponse.__name__],
)View on GitHub (pinned to ef8544b173)
Solutions
- Unpublish or detach the workflow from the app before deleting.
- Delete or repoint dependent apps/schedules first.
- Read the 400 description to see which app references the workflow.
Example fix
// before: deleting an in-use workflow DELETE /apps/<id>/workflows/<wid> // after: detach then delete // 1) switch the app to a different/published workflow // 2) DELETE /apps/<id>/workflows/<wid>
Defensive patterns
Strategy: validation
Validate before calling
workflow = workflow_service.get_workflow(app_model, workflow_id)
if workflow_service.is_in_use(workflow):
raise RuntimeError("workflow is in use; detach or unpublish before deleting") Type guard
def is_safe_to_delete(workflow, service) -> bool:
return workflow is not None and not service.is_in_use(workflow) Try / catch
try:
client.delete(f"/console/api/apps/{app_id}/workflows/{workflow_id}")
except HTTPError as err:
if err.response.status_code == 400 and "in use" in err.response.text.lower():
# detach/republish, then retry
detach_workflow(app_id, workflow_id)
client.delete(f"/console/api/apps/{app_id}/workflows/{workflow_id}")
else:
raise Prevention
- Before DELETE, ensure no app/schedule references the workflow.
- Surface the 400 description so the referencing app is identified.
- Prefer publishing a new workflow over deleting an active one.
When it happens
Trigger: `DELETE /apps/<app_id>/workflows/<workflow_id>` is called for a workflow that is currently published/active or otherwise referenced by the app, so `delete_workflow` raises `WorkflowInUseError`.
Common situations: Trying to delete the only/active workflow of an app, or deleting a workflow that another app or scheduled job still references.
Related errors
- source workflow must be published
- Cannot delete workflow that is currently in use by pipeline
- {str(e)}
- usage_missing_arg
- usage_invalid_flag
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/85c501dac5f28421.
Report an issue: GitHub.