langgenius / langgenius/dify

Workflow draft variable deletion leaves offloaded files orphaned

Open
#41,545 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
156k
Forks
24.6k
Avg merge
22h 9m
Merged PRs (30d)
610

Description

## Background

Workflow draft variables can offload large values into object storage through an `UploadFile` and a `WorkflowDraftVariableFile` record. The service exposes user-level, node-level, app-level, and single-variable deletion paths.

## Affected version

Latest `main` at `57144b0094b083815824295a41bcdef7a43c181c`.

## Steps to reproduce

1. Create a `WorkflowDraftVariableFile` and its associated `UploadFile` and storage object.
2. Create a `WorkflowDraftVariable` whose `file_id` references that offload record.
3. Call `WorkflowDraftVariableService.delete_user_workflow_variables(app_id, user_id)` and commit.
4. Query the three database tables and inspect the storage deletion call.

The same cleanup gap exists in node-level and app-level service deletion. The single-variable path deletes the variable and `UploadFile`, but leaves its `WorkflowDraftVariableFile` row. Reset paths that discard stale draft variables also delete only the variable row.

## Expected behavior

Deleting a draft variable also removes its associated object-storage data, `UploadFile`, and `WorkflowDraftVariableFile` record. Bulk deletion should preserve unrelated users, apps, and nodes.

## Actual behavior

The draft variable row is removed, while the offload resources remain. A minimal SQLite reproduction produced:

```text
workflow_draft_variables: 0
workflow_draft_variable_files: 1
upload_files: 1
storage delete calls: 0
```

## Impact

Normal console operations such as clearing a user's draft variables, deleting a node's variables, and replacing an app during DSL import can accumulate unreachable database records and storage objects. Repeated use causes persistent database and object-storage growth.

## Root cause

`delete_user_workflow_variables`, `delete_app_workflow_variables`, and `_delete_node_variables` issue direct bulk deletes against `workflow_draft_variables` without loading or cleaning `file_id` resources. `delete_variable` also omits deletion of the loaded `WorkflowDraftVariableFile` in its successful offload branch, while reset branches bypass cleanup by deleting the variable directly.

## Duplicate check

- #23735 / #23737 addressed draft variable rows left after deleting an app. The later app-removal task has dedicated offload cleanup, but the service deletion paths above do not use it.
- #37984 tracks file-reference ownership boundaries, not deletion cleanup.
- #30794 only proposed removing a duplicated `Session.delete(upload_file)` call and was closed without merge.
- Searches covered open and closed issues, open/draft/closed/merged PRs, relevant commits, Discussions, and release notes using the model names, deletion methods, offload terminology, orphan symptoms, and storage-cleanup terms. No equivalent fix is present on `main`.

Contributor guide

Open the contributing guide

Research direction

Start by locating WorkflowDraftVariableService and trace delete_user_workflow_variables, delete_app_workflow_variables, _delete_node_variables, delete_variable, and the reset paths. Run the minimal SQLite reproduction described in the issue and inspect database rows and storage deletion calls. Done means every deletion path removes the object-storage data, UploadFile, and WorkflowDraftVariableFile while preserving unrelated users, apps, and nodes.

Written by the indexing model from the issue text.

Assessment

Domain
backend, cloud, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.