Skip to content

Deleting an EmailTemplate in a nested email folder is never recorded by source tracking; the delete is re-sent on every deploy #3659

Closed
forcedotcom/source-deploy-retrieve
#1846

Description

@SalesforceRocks

Related issue: #2870 (same kind of name mismatch, different metadata type)

Command: sf project deploy start, sf project deploy preview

Org type: Sandbox with source tracking

Did this work before? Unknown

Summary

With source tracking on, deleting an EmailTemplate that sits in a nested email folder succeeds in the org, but local tracking never records it. sf project deploy preview keeps listing the template under "to delete", and every later sf project deploy start re-sends the delete and gets No EmailTemplate named: <folder>/<name> found — a failure, or a warning with --ignore-warnings. Only sf project reset tracking clears it.

Steps to reproduce

  1. In a source-tracked sandbox or scratch org, create a project with:
force-app/main/default/email/Outer.emailFolder-meta.xml
force-app/main/default/email/Outer/Inner.emailFolder-meta.xml
force-app/main/default/email/Outer/Inner/My_Template.email
force-app/main/default/email/Outer/Inner/My_Template.email-meta.xml
  1. sf project deploy start — succeeds; sf project deploy preview is clean.
  2. Delete My_Template.email and My_Template.email-meta.xml locally.
  3. sf project deploy start — succeeds; the template is gone from the org.
  4. sf project deploy preview --json
  5. sf project deploy start again.

Expected result

After step 4, preview shows nothing to delete and later deploys send no delete.

Actual result

  • Step 5: result.toDelete still lists EmailTemplate Outer/Inner/My_Template, on every run.
  • Step 6: No EmailTemplate named: Inner/My_Template found. The deploy fails without --ignore-warnings.

Likely cause

The Metadata API answers with different names for the same component:

  • create/change: fullName = Outer/Inner/My_Template
  • delete: fullName = Inner/My_Template, deleted = true

source-deploy-retrieve names the local component Outer/Inner/My_Template (calculateName in src/resolve/adapters/baseSourceAdapter.ts). buildFileResponsesFromComponentSet in src/client/metadataApiDeploy.ts matches deploy messages to components by type#fullName, so the delete success is never matched and no Deleted FileResponse is produced. deleteNotFoundToFileResponses misses the same way. SourceTracking.updateTrackingFromDeploy therefore never commits the deleted files to the local shadow repo. sanitizeDeployMessage has special cases for LWC, Document and EmailTemplateFolder, but none for this.

Other nested in-folder types (Report, Dashboard, Document) may behave the same; not tested.

System information

@salesforce/cli/2.152.14 darwin-arm64 node-v24.20.0
Darwin 24.6.0
deploy-retrieve 4.2.2 (core)
@salesforce/source-deploy-retrieve 12.10.1
Org API version: 68.0

Not verified against the very latest CLI release; the matching code on source-deploy-retrieve's main looks unchanged. Observed on our own project layout (a template two folders deep); the Outer/Inner steps above are that layout with generic names.

Workaround

sf project reset tracking after the deploy that performed the delete.

Activity

  1. added
    bugIssue or pull request that identifies or fixes a bug
    on Oct 5, 2026
  2. git2gus commented on Oct 5, 2026

    @git2gus

    This issue has been linked to a new work item: W-24411539

  3. k80bowman commented on Oct 5, 2026

    @k80bowman

    Thank you for providing such detailed information. We've been able to validate the problem, we'll work on getting it fixed.

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

    bugIssue or pull request that identifies or fixes a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions