3

I created a Namespaced Unlocked package out of that repo.

https://github.com/rsoesemann/salesforce-isv-cockpit/blob/master/force-app/main/default/flows/NotifySlackOnError.flow-meta.xml

It contains a Flow with a Formula that references packaged Fields, but all the other Field and Object references don't hardcode any namespace.

When the Flow runs from the Unlocked package, it fails because the formula fields cannot be referenced, and the values stay NULL.

enter image description here

I found that strange as other field references like $Setup.Settings_c.txt_SlackChannel_c also have no namespace but are correctly recognized.

Is that a Flow Formula issue, or what am I doing wrong?

3 Answers 3

4

Flows do, indeed, need certain elements to include the namespace. I think it's a bug but we live with it by ensuring the namespace prefix is included where required. For us, this includes:

  • Fields within $Record.
  • Fields in custom settings in $Setup (though I see you didn't have that problem).
  • Queried and assigned fields (Get Records, Assignment).
  • Fields used in conditions.
  • Object and field API names passed to the lookup component.
  • Etc.

Fundamentally, flow handling of namespace is inconsistent with the rest of packaging and you should err on the side of providing the namespace prefix everywhere in the XML.

3

I agree with Phil that this is a bug manifesting in a variety of places within Flow metadata, where the Metadata API or packaging system fails to correctly resolve the component reference to the namespaced component. This usually manifests as functional failures in the installed package, although I think I remember one situation where the package failed to upload as well.

My team at Salesforce.org/Industries has worked with the Flow team in the past to address some of these bugs. It's hard to identify them all.

Because we heavily prioritize not including the package's namespace in metadata, we use dynamic injection of the namespace when we deploy metadata. This is done via a feature called source transforms in CumulusCI.

In the past we have typically used a basic find-and-replace rubric with a token in the Flow metadata, like

<name>%%%NAMESPACE%%%AppNotification</name>

which gets injected with a blank (for regular orgs) or the actual namespace (for packaging). The cumulusci.yml configuration looks like this:

flows:
    deploy_packaging:
        options:
            deploy:
                transforms:
                    - transform: find_replace
                      options:
                          patterns:
                              - find: "%%%NAMESPACE%%%"
                                replace: my_namespace

That strategy doesn't work as well for Flows that are under active development because the token doesn't survive a round-trip through an org (push/pull) and has to be manually maintained in the required spots.

We recently introduced a more sophisticated strategy that supports XPath-based replacement, which would probably work well for this use case. XPath-based replacement does survive roundtrips through the org, because it targets the structural location in the metadata where the namespace needs to be injected.

3
  • I like that you're supporting (or trying to support) this flow "limitation" but it should be possible to deal with this using bare metal Salesforce CLI and packaging functionality. Is there any attempt to resolve this suite of bugs in the platform itself?
    – Phil W
    Commented Nov 23, 2023 at 10:13
  • @PhilW Yeah, we've worked with the Flow team on the ones that bit us in the past. There's a million different places a namespaced component reference can appear, though. There are also a few situations where you might store a component reference in a part of the Flow XML that is technically text, not a component reference, so it won't get processed at all. (Ex. parameter values).
    – David Reed
    Commented Nov 24, 2023 at 6:40
  • Apex handles this sort of thing. I just wished flow matched it in support for packaging.
    – Phil W
    Commented Nov 24, 2023 at 7:04
2

I encountered this recently with two requirements:

Requirement 1) Store metadata without the Namespace Prefix. Why? So that the code can be deployed unmanaged, so that it works with SFDX out of the box (ie works for Flows under active development), so that test packages can be created with other namespaces, so that both 1GP/2GP can be produced from same source, and so on.

Requirement 2) Deploy only truly necessary NS prefixes in Flow metadata. Why? So that we avoid subscribers hitting the 50 Flow Versions limit. CI deploying extra namespaces in Flow metadata will cause Salesforce to create duplicate flow versions. Deleting flow versions in packaging orgs does not help subscribers. Upgrades are blocked when they hit the 50 Flow Versions limit on their side.

I believe these are the necessary replacements:

Rule: Email Alert elements in <actionCalls>

  • When: the actionType is emailAlert
  • Then: prefix any <actionName>
  • Then: prefix any <nameSegment>
Example: <actionName>Object__c.Email_Alert_Name</actionName>
Becomes: <actionName>NS__Object__c.Email_Alert_Name</actionName>

Rule: Decision elements in <rules>

  • When the leftValueReference refers to global $Record
  • Then: prefix any Field__c
  • Then: prefix any Related__r
Example: <leftValueReference>$Record.Field__c</leftValueReference>
Becomes: <leftValueReference>$Record.NS__Field__c</leftValueReference>

Rule: Formula resources in <expression>

  • When the expression refers to global $Record
  • Then: prefix any {!$Record.Field__c}
  • Then: prefix any {!variable.Field__c} also
  • (Yes, the presence of $Record taints all other variables!)
Example: <expression>{!record.Field__c}</expression>
Remains: <expression>{!record.Field__c}</expression>

Example: <expression>{!$Record.F1__c} + {!record.F2__c}</expression>
Becomes: <expression>{!$Record.NS__F1__c} + {!record.NS__F2__c}</expression>

Rule: Screens in <fields>

  • When the extensionName is flowruntime:lookup
  • Then: prefix any Field__c
Example: <stringValue>Field__c</stringValue>
Becomes: <stringValue>NS__Field__c</stringValue>

The above will prevent duplicate versions for Record Triggered, Autolaunched, and Screen flows. I hope Salesforce one day canonicalizes the process, until then, here is how to obtain the canonical NS prefixes:

  1. Create a 1GP packaging org with a namespace prefix
  2. In the GUI, create "kitchen sink" flow(s) with 1 of every element
  3. Specify 1 of every attribute with $Record / Field__c references
  4. Add 1 of every formula/template resource, also with references
  5. Retrieve the flow and inspect where the NS appears.

To verify your canonicalization process is correct, you can deploy a flow. If SF creates a duplicate version, the process is not correct. I hope this might help anybody still using Ant or regexp replacements.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .