Skip to content

application: deleteApplicationResources TransactionalOperator injected but never applied - server kill mid-delete leaves ghost application record #42117

Description

@harsh4vardhan

Bug Description

deleteApplicationResources performs six sequential async operations to archive an application's resources. A TransactionalOperator is injected into the class but never applied to this chain. If the server is killed between any two steps, the application enters a permanently broken state: some resources are deleted, the application document still exists, but the remaining resources are gone.

Affected file

�pp/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java:

Field declared at line 131:
java private final TransactionalOperator transactionalOperator;

Delete chain at lines 579-72 with no .as(transactionalOperator::transactional):
java protected Mono<Application> deleteApplicationResources(Application application) { return actionPermissionMono .flatMap(...actionCollectionService.archiveActionCollectionByApplicationId(...)) .then(...newActionService.archiveActionsByApplicationId(...)) .then(...newPageService.archivePagesByApplicationId(...)) .then(themeService.archiveApplicationThemes(application)) .then(userDataService.removeApplicationFromAllFavorites(...)) .then(applicationService.archive(application)); // step 6 - may never run }

For contrast, ImportServiceCEImpl.java:552 correctly uses .as(transactionalOperator::transactional).

Failure scenario

  1. User deletes an application with 50 pages and 200 actions.
  2. Steps 1-4 complete: action collections, actions, pages, themes all archived.
  3. Server receives SIGTERM during step 5 or 6.
  4. �pplicationService.archive(application) never runs.
  5. The application document remains in MongoDB, visible in the workspace list.
  6. Opening the application fails (no pages/actions). Attempting to delete again partially succeeds but leaves the document stuck since steps 1-4 are now no-ops.
  7. The application is permanently a "ghost" record that cannot be opened or deleted.

Fix

Apply the injected operator to the delete chain:

java protected Mono<Application> deleteApplicationResources(Application application) { return actionPermissionMono .flatMap(...) ... .then(applicationService.archive(application)) .as(transactionalOperator::transactional); }

Environment

Appsmith elease branch (2026-08-13), Java/Spring WebFlux, MongoDB.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions