lightning-flow-scanner-core icon indicating copy to clipboard operation
lightning-flow-scanner-core copied to clipboard

MissingNullHandler triggered on subflow output variables

Open filiprafalowicz opened this issue 11 months ago • 6 comments

I have an Autolaunched Flow that based on provided input variable will run some queries and return results in output variables. Just to have easier steps to reproduce, I have created a sample flow that has recordId input variable and based on the prefix it will query either User or Group objects and set output variables with results of the queries:

<?xml version="1.0" encoding="UTF-8"?>
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>60.0</apiVersion>
    <assignments>
        <name>Set_Error_Message</name>
        <label>Set Error Message</label>
        <locationX>314</locationX>
        <locationY>350</locationY>
        <assignmentItems>
            <assignToReference>errorMessage</assignToReference>
            <operator>Assign</operator>
            <value>
                <stringValue>Error when retrieving records</stringValue>
            </value>
        </assignmentItems>
    </assignments>
    <decisions>
        <name>Check_object_type</name>
        <label>Check object type</label>
        <locationX>578</locationX>
        <locationY>134</locationY>
        <defaultConnectorLabel>Default Outcome</defaultConnectorLabel>
        <rules>
            <name>User</name>
            <conditionLogic>and</conditionLogic>
            <conditions>
                <leftValueReference>recordId</leftValueReference>
                <operator>StartsWith</operator>
                <rightValue>
                    <stringValue>005</stringValue>
                </rightValue>
            </conditions>
            <connector>
                <targetReference>Get_User</targetReference>
            </connector>
            <label>User</label>
        </rules>
        <rules>
            <name>Queue</name>
            <conditionLogic>and</conditionLogic>
            <conditions>
                <leftValueReference>recordId</leftValueReference>
                <operator>StartsWith</operator>
                <rightValue>
                    <stringValue>00G</stringValue>
                </rightValue>
            </conditions>
            <connector>
                <targetReference>Get_Queue</targetReference>
            </connector>
            <label>Queue</label>
        </rules>
    </decisions>
    <description>Subflow that throws MissingNullHandler</description>
    <environments>Default</environments>
    <interviewLabel>Subflow_Missing {!$Flow.CurrentDateTime}</interviewLabel>
    <label>Subflow_MissingNullHandler</label>
    <processMetadataValues>
        <name>BuilderType</name>
        <value>
            <stringValue>LightningFlowBuilder</stringValue>
        </value>
    </processMetadataValues>
    <processMetadataValues>
        <name>CanvasMode</name>
        <value>
            <stringValue>AUTO_LAYOUT_CANVAS</stringValue>
        </value>
    </processMetadataValues>
    <processMetadataValues>
        <name>OriginBuilderType</name>
        <value>
            <stringValue>LightningFlowBuilder</stringValue>
        </value>
    </processMetadataValues>
    <processType>AutoLaunchedFlow</processType>
    <recordLookups>
        <name>Get_Queue</name>
        <label>Get Queue</label>
        <locationX>578</locationX>
        <locationY>242</locationY>
        <assignNullValuesIfNoRecordsFound>true</assignNullValuesIfNoRecordsFound>
        <faultConnector>
            <isGoTo>true</isGoTo>
            <targetReference>Set_Error_Message</targetReference>
        </faultConnector>
        <filterLogic>and</filterLogic>
        <filters>
            <field>Type</field>
            <operator>EqualTo</operator>
            <value>
                <stringValue>Queue</stringValue>
            </value>
        </filters>
        <filters>
            <field>Id</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>recordId</elementReference>
            </value>
        </filters>
        <object>Group</object>
        <outputReference>queueRecord</outputReference>
        <queriedFields>Id</queriedFields>
    </recordLookups>
    <recordLookups>
        <name>Get_User</name>
        <label>Get User</label>
        <locationX>50</locationX>
        <locationY>242</locationY>
        <assignNullValuesIfNoRecordsFound>true</assignNullValuesIfNoRecordsFound>
        <faultConnector>
            <targetReference>Set_Error_Message</targetReference>
        </faultConnector>
        <filterLogic>and</filterLogic>
        <filters>
            <field>Id</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>recordId</elementReference>
            </value>
        </filters>
        <object>User</object>
        <outputReference>userRecord</outputReference>
        <queriedFields>Id</queriedFields>
    </recordLookups>
    <start>
        <locationX>452</locationX>
        <locationY>0</locationY>
        <connector>
            <targetReference>Check_object_type</targetReference>
        </connector>
    </start>
    <status>Draft</status>
    <variables>
        <name>errorMessage</name>
        <dataType>String</dataType>
        <isCollection>false</isCollection>
        <isInput>false</isInput>
        <isOutput>true</isOutput>
    </variables>
    <variables>
        <name>queueRecord</name>
        <dataType>SObject</dataType>
        <isCollection>false</isCollection>
        <isInput>false</isInput>
        <isOutput>true</isOutput>
        <objectType>Group</objectType>
    </variables>
    <variables>
        <name>recordId</name>
        <dataType>String</dataType>
        <isCollection>false</isCollection>
        <isInput>true</isInput>
        <isOutput>false</isOutput>
    </variables>
    <variables>
        <name>userRecord</name>
        <dataType>SObject</dataType>
        <isCollection>false</isCollection>
        <isInput>false</isInput>
        <isOutput>true</isOutput>
        <objectType>User</objectType>
    </variables>
</Flow>

When I run sf flow scan command, I get following output:

=== Flow: Subflow_MissingNullHandler (2 results)
Type: AutoLaunchedFlow

RULE                  TYPE           NAME
────────────────────  ─────────────  ─────────
Missing Null Handler  recordLookups  Get_Queue
Missing Null Handler  recordLookups  Get_User

In flows like this, I would expect to not see MissingNullHandler rule violated as there is no point of adding a decision after Get Records. Null check will be handled by the parent flow before variables are used (btw, that could be created as a new rule - do null check on output variables from subflows before you use them). I think quick fix would be to update the rule to not show errors when Get Records is connected directly to the End node.

filiprafalowicz avatar Mar 09 '24 17:03 filiprafalowicz