Hi @kjakubiak & @vinnysail
Attaching the trace and the xml, this time an error was thrown stating unknown object.
The state of the approvalItem is set to “finished” after the manager approval. Could that be the problem?
Starting step Start
Ending step Start
Starting step Start Approval
Ending step Start Approval
Starting step Manager Approval
Starting approval group in mode serial
Starting approval for Jakob.Brouwer
Opening work item: Manager Approval - Account Changes for User: Amanda.Ross
Assimilating work item: Manager Approval - Account Changes for User: Amanda.Ross
Ending approval for Jakob.Brouwer
Ending approval group in mode serial
Ending step Manager Approval
Starting step Build Owner ApprovalSet
Step result variable: tmpApprovalSet
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE ApprovalSet PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<ApprovalSet>
<ApprovalItem application="AD" approver="Jakob.Brouwer" assignmentId="739092a3bb70495783024737b5ae0772" displayValue="IDNB\Account Operators" id="0246fdeedddc4c3796d76e8165b62e09" name="memberOf" nativeIdentity="cn=Amanda.Ross,ou=SailPointIIQ,dc=IDNB,dc=com" operation="Add" owner="Jakob.Brouwer" state="Finished" value="CN=Account Operators,CN=Builtin,DC=IDNB,DC=COM">
<Attributes>
<Map>
<entry key="attachmentConfigList"/>
<entry key="attachments"/>
<entry key="flow" value="AccessRequest"/>
<entry key="id" value="c0a81a838cd0144b818cd37a08f0045e"/>
<entry key="interface" value="LCM"/>
<entry key="operation" value="EntitlementAdd"/>
</Map>
</Attributes>
</ApprovalItem>
</ApprovalSet>
Ending step Build Owner ApprovalSet
Starting step Process Owner
App name is not null
Owner is not null
App Owner Name not null
AttrName and Vals not null
Val not null
Entering Get Managed Attribute Owner Heimdall
MA is not null
ItemApp = not null and is AD
Group Type *********Security
Entering Further to call custom object*********
Custom Object not null*********
Custom Attribute not null*********
******* Owner fetched from custom object = Carl.Foster
******* Successfully Returned from getManagedAttributeOwnerHeimdall Method
Managed Attribute owner not null
******* Successfully Returned from resolveItemOwnerHeimdall Method
ApprovalOwnersString is not null: "Carl.Foster"
Step result variable: approvalOwner
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE String PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<String>"Carl.Foster"</String>
Ending step Process Owner
Starting step Show Owner Calculated
"Carl.Foster"
Ending step Show Owner Calculated
Starting step Owner Approval
2024-01-25T07:05:51,833 ERROR http-nio-8080-exec-10 sailpoint.api.Workflower:4605 - An unexpected error occurred: Unknown object: "Carl.Foster"
sailpoint.tools.GeneralException: Unknown object: "Carl.Foster"
at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:1064) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:948) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:935) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
at sailpoint.api.ObjectUtil.getObjects(ObjectUtil.java:1094) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
at sailpoint.api.Workflower.expandApprovalScriptResult(Workflower.java:6496) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
at sailpoint.api.Workflower.expandApproval(Workflower.java:6407) ~[identityiq.jar:8.4 Build bdd0ed4de58-20230919-192552]
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1704312600007" explicitTransitions="true" id="c0a81a838cd01069818cd0f275c70317" modified="1706195084532" name="Identity Request Approve" significantModified="1706195084532" type="Subprocess">
<Variable input="true" name="identityName" required="true">
<Description>The name of the identity object being modified.</Description>
</Variable>
<Variable input="true" name="batchRequestId">
<Description>Batch request id.</Description>
</Variable>
<Variable initializer="script:(identityDisplayName != void) ? identityDisplayName : resolveDisplayName(identityName)" input="true" name="identityDisplayName">
<Description>The displayName of the identity being updated.
This may be passed in, if not the script queries for this
using a projection query and falls back to the name.</Description>
</Variable>
<Variable initializer="script:getIdentityProperty(identityName, "id")" input="true" name="identityId">
<Description>The id of the identity being updated.</Description>
</Variable>
<Variable input="true" name="identityRequestId">
<Description>The ID of the IdentityRequest for this request.</Description>
</Variable>
<Variable input="true" name="approvalScheme" required="true">
<Description>A csv string that specifies how approvals should be generated for
the incoming request.
The value can be any of the values below, combined together but
are always processed in this order:
1. manager
2. owner
3. securityOfficer
Any rejected items from previous approvals will be omitted from the
next phase of approvers.
none - disabled approvals
owner - the object owner gets the approval
For Role approvals this is the Role object owner. When dealing
with things like Unlock and other account level changes
the approvals will be assigned to the the application owner.
manager - The manager will get all approvals
securityOfficer - The identity named security the security in the variable
securityOfficerName.</Description>
</Variable>
<Variable initializer="serial" input="true" name="approvalMode">
<Description>A string that specifies how we should handle the approvals.
By default this is serial since most of these request with
the exception of manager transfers will have only one approver.
parallel
Approvals are processed concurrently and there must be consensus,
we wait for all approvers to approve. The first approver that
rejects terminates the entire approval.
parallelPoll
Approvals are processed concurrently but consensus is not required.
All approvals will be processed, we don&#39;t stop if there are any
rejections.
serial
Approvals are processed one at a time and there must be consensus.
The first approver that rejects terminates the entire approval.
serialPoll
Approvals are processed in order but consensus is not required.
All approvals will be processed, we don&#39;t stop if there are any
rejections. In effect we are &quot;taking a poll&quot; of the approvers.
any
Approvals are processed concurrently, the first approver to
respond makes the decision for the group.</Description>
</Variable>
<Variable input="true" name="fallbackApprover" required="true">
<Description>A String that specifies the name of the Identity that will
be assigned any approvals where the owner of the approver
can&#39;t be resolved. Example if the scheme is &quot;owner&quot; and the
application doesn&#39;t specify and owner.</Description>
</Variable>
<Variable input="true" name="securityOfficerName">
<Description>The name of the identity that will be sent approvals
during security officer approvals.</Description>
</Variable>
<Variable input="true" name="batchRequestApprover">
<Description>Identity responsible for approving batch requests.</Description>
</Variable>
<Variable initializer="false" input="true" name="includeRejectedItemsInApprovalChain">
<Description>When using multi approvalSchemes a flag to indicate if new
approvals in the chain will include rejected items.</Description>
</Variable>
<Variable input="true" name="policyViolations">
<Description>List of policy violations that were found during our initial policy scan.
This list is passed into each work item so the approvers can see
pending violations.</Description>
</Variable>
<Variable input="true" name="flow">
<Description>The name of the LCM flow that launched this workflow.
This is one of these values:
AccountsRequest
EntitlementsRequest
RolesRequest
IdentityCreateRequest
IdentityEditRequest
ForgotPassword
ExpiredPassword
PasswordRequest
joiner
mover
leaver
AttributeSync</Description>
</Variable>
<Variable input="true" name="trace">
<Description>Used for debugging this subprocess and when set to true trace
statements will be sent to stdout.</Description>
</Variable>
<Variable input="true" name="approvalSet" output="true">
<Description>This attributes is set during the &quot;Build Approval Set&quot; step,
which builds this list by going through the ProvisioningPlan
to build the line items that need to be approved,
This variable includes all ApprovalItems that are part of
the request process and is updated during the AfterScript
of the approval process by assimilating the decisions
and comments from the Approvals copy of the ApprovalItem.</Description>
</Variable>
<Variable initializer="LCM Identity Update Approval" input="true" name="managerEmailTemplate">
<Description>Name of the email template to use when manager of pending approvals.</Description>
</Variable>
<Variable initializer="LCM Identity Update Approval" input="true" name="ownerEmailTemplate">
<Description>Name of the email template to use when notifying the owner of pending approvals.</Description>
</Variable>
<Variable initializer="LCM Identity Update Approval" input="true" name="securityOfficerEmailTemplate">
<Description>Name of the email template to use when notifying the security officer of pending approvals.</Description>
</Variable>
<Variable initializer="Batch Approval" input="true" name="batchApproverEmailTemplate">
<Description>Name of the email template to use when notifying the batch approver of pending approval.</Description>
</Variable>
<Variable input="true" name="workItemComments">
<Description>List of global workflow comments to be appended to the approval workitem.</Description>
</Variable>
<Variable input="true" name="managerElectronicSignature">
<Description>The name of the electronic signature object that should be used when workitems
are completed by a manager.</Description>
</Variable>
<Variable input="true" name="ownerElectronicSignature">
<Description>The name of the electronic signature object that should be used when workitems
are completed by object owners.</Description>
</Variable>
<Variable input="true" name="securityOfficerElectronicSignature">
<Description>The name of the electronic signature object that should be used when workitems
are completed by the security officer.</Description>
</Variable>
<Variable input="true" name="batchApproverElectronicSignature">
<Description>The name of the electronic signature object that should be used when workitems
are completed by the batch approver when performing batch operations.</Description>
</Variable>
<Variable input="true" name="workItemPriority">
<Description>String version of WorkItem.level that will be used
to set the priority of the workitems generated
as part of any generated approvals.</Description>
</Variable>
<Variable name="tmpApprovalSet">
<Description>Temporary and transient ApprovalSet used to hold filtered
approval sets as we transition through the approval chain.</Description>
</Variable>
<Variable name="tmpApproval">
<Description>Temporary and transient list of Approval object used to hold filtered
approval as we transition through the approval chain.</Description>
</Variable>
<Variable name="approvalOwner"/>
<RuleLibraries>
<Reference class="sailpoint.object.Rule" id="c0a81a838cd01069818cd0f122ca018a" name="Approval Library"/>
<Reference class="sailpoint.object.Rule" id="c0a81a838d2d1ae1818d35a31aa202a2" name="custom-ApprovalLibrary"/>
<Reference class="sailpoint.object.Rule" id="c0a81a838cd01069818cd0f12867019d" name="LCM Workflow Library"/>
</RuleLibraries>
<Step icon="Start" name="Start" posX="28" posY="10">
<Transition to="Start Approval"/>
</Step>
<Step icon="Task" name="Start Approval" posX="28" posY="149">
<Transition to="Manager Approval" when="script:isApprovalEnabled(approvalScheme, "manager")"/>
<Transition to="Build Owner ApprovalSet" when="script:isApprovalEnabled(approvalScheme, "owner")"/>
<Transition to="Build Security Officer ApprovalSet" when="script:isApprovalEnabled(approvalScheme, "securityOfficer")"/>
<Transition to="Batch Request Approval" when="script:isApprovalEnabled(approvalScheme, "batchRequest")"/>
<Transition to="end"/>
</Step>
<Step icon="Approval" name="Manager Approval" posX="172" posY="7">
<Approval mode="serial" name="Manager Approval" owner="call:buildManagerApproval" renderer="lcmWorkItemRenderer.xhtml" send="approvalSet,identityDisplayName,identityName,policyViolations">
<AfterScript>
<Source>
import sailpoint.workflow.IdentityRequestLibrary;
assimilateWorkItemApprovalSet(wfcontext, item, approvalSet);
IdentityRequestLibrary.assimilateWorkItemApprovalSetToIdentityRequest(wfcontext, approvalSet);
auditDecisions(item);
</Source>
</AfterScript>
<Arg name="workItemIdentityRequestId" value="ref:identityRequestId"/>
<Arg name="workItemElectronicSignature" value="ref:managerElectronicSignature"/>
<Arg name="workItemRequester" value="$(launcher)"/>
<Arg name="workItemDescription" value="Manager Approval - Account Changes for User: $(identityDisplayName)"/>
<Arg name="workItemNotificationTemplate" value="ref:managerEmailTemplate"/>
<Arg name="workItemTargetClass" value="sailpoint.object.Identity"/>
<Arg name="workItemTargetName" value="$(identityName)"/>
<Arg name="workItemTargetId" value="$(identityId)"/>
<Arg name="workItemPriority" value="ref:workItemPriority"/>
</Approval>
<Description>
If approvalScheme contains manager, send an approval for all
requested items in the request. This approval will get the entire
approvalSet as part of the workitem.
</Description>
<Transition to="Build Owner ApprovalSet" when="script:isApprovalEnabled(approvalScheme, "owner")"/>
<Transition to="Build Security Officer ApprovalSet" when="script:isApprovalEnabled(approvalScheme, "securityOfficer")"/>
<Transition to="end"/>
</Step>
<Step icon="Task" name="Build Owner ApprovalSet" posX="237" posY="212" resultVariable="tmpApprovalSet">
<Script>
<Source>filterApprovalSetHeimdall(approvalSet,includeRejectedItemsInApprovalChain,false);
</Source>
</Script>
<Transition to="Process Owner"/>
</Step>
<Step name="Process Owner" posX="323" posY="378" resultVariable="approvalOwner">
<Return name="approvalOwner" to="approvalOwner"/>
<Script>
<Source>String approvalOwnersString = null;
String approvalOwnersStringReturn = null;
List<ApprovalItem> items = approvalSet.getItems();
if (items != null) {
for (ApprovalItem item : items) {
if (item != null) {
approvalOwnersString = resolveItemOwnerHeimdall(item);
approvalOwnersStringReturn = "\"" + approvalOwnersString + "\"";
if (approvalOwnersString != null) {
System.out.println("ApprovalOwnersString is not null: " + approvalOwnersStringReturn);
return approvalOwnersStringReturn; // Return the value if it's not null
} else {
System.out.println("ApprovalOwnersString is null");
}
}
}
}</Source>
</Script>
<Transition to="Show Owner Calculated"/>
</Step>
<Step action="script:System.out.println(approvalOwner);" name="Show Owner Calculated" posX="581" posY="366">
<Transition to="Owner Approval"/>
</Step>
<Step icon="Approval" name="Owner Approval" posX="390" posY="213">
<Approval mode="ref:approvalMode" name="Owner Approval" owner="ref:approvalOwner" renderer="lcmWorkItemRenderer.xhtml" send="identityDisplayName,identityName,policyViolations,approvalOwner">
<AfterScript>
<Source>
import sailpoint.workflow.IdentityRequestLibrary;
if ( item == null )
return;
assimilateWorkItemApprovalSet(wfcontext, item, approvalSet);
IdentityRequestLibrary.assimilateWorkItemApprovalSetToIdentityRequest(wfcontext, approvalSet);
auditDecisions(item);
</Source>
</AfterScript>
<Arg name="approvalSet" value="ref:tmpApprovalSet"/>
<Arg name="workItemDescription" value="Owner Approval - Account Changes for User: $(identityDisplayName)"/>
<Arg name="workItemElectronicSignature" value="ref:ownerElectronicSignature"/>
<Arg name="workItemIdentityRequestId" value="ref:identityRequestId"/>
<Arg name="workItemNotificationTemplate" value="ref:ownerEmailTemplate"/>
<Arg name="workItemPriority" value="ref:workItemPriority"/>
<Arg name="workItemRequester" value="$(launcher)"/>
</Approval>
<Description>
If approvalScheme contains owner, send approvals out to all
of the owners for items in the request. The main approvalSet
is broken up into owner specific approval sets and assimilated
back into the main approvalset as decisions are made.
The previous decisions made on the items will be present along
with any comments made by the manager.
This step will be skipped if all items are
rejected and includeRejectedItemsInApprovalChain is set to false
</Description>
<Transition to="Build Security Officer ApprovalSet" when="script:isApprovalEnabled(approvalScheme, "securityOfficer")"/>
<Transition to="end"/>
</Step>
<Step action="script:filterApprovalSet(approvalSet,includeRejectedItemsInApprovalChain,false)" icon="Task" name="Build Security Officer ApprovalSet" posX="309" posY="61" resultVariable="tmpApprovalSet">
<Transition to="Security Officer Approval"/>
</Step>
<Step condition="script:!isNull(tmpApprovalSet) && !tmpApprovalSet.isEmpty()" icon="Approval" name="Security Officer Approval" posX="698" posY="59">
<Approval mode="serial" owner="call:buildSecurityOfficerApproval" renderer="lcmWorkItemRenderer.xhtml" send="identityDisplayName,identityName,policyViolations">
<AfterScript>
<Source>
import sailpoint.workflow.IdentityRequestLibrary;
assimilateWorkItemApprovalSet(wfcontext, item, approvalSet);
IdentityRequestLibrary.assimilateWorkItemApprovalSetToIdentityRequest(wfcontext, approvalSet);
</Source>
</AfterScript>
<Arg name="approvalSet" value="ref:tmpApprovalSet"/>
<Arg name="workItemElectronicSignature" value="ref:securityOfficerElectronicSignature"/>
<Arg name="workItemIdentityRequestId" value="ref:identityRequestId"/>
<Arg name="workItemRequester" value="$(launcher)"/>
<Arg name="workItemDescription" value="Security Officer Approval - Account Changes for User: $(identityDisplayName)"/>
<Arg name="workItemNotificationTemplate" value="ref:securityOfficerEmailTemplate"/>
<Arg name="workItemPriority" value="ref:workItemPriority"/>
<Arg name="workItemTargetClass" value="sailpoint.object.Identity"/>
<Arg name="workItemTargetName" value="ref:identityName"/>
<Arg name="workItemTargetId" value="ref:identityId"/>
</Approval>
<Description>
If approvalScheme contains securityOfficer and the securityOfficeName is
non null this step will send items with decisions and comments
from the cart for final decision.
The previous decisions made on the item will be present along with
any comments made in previous approval steps.
</Description>
<Transition to="Batch Request Approval"/>
</Step>
<Step icon="Approval" name="Batch Request Approval" posX="833" posY="59">
<Approval mode="serial" owner="ref:batchRequestApprover" renderer="lcmWorkItemRenderer.xhtml" send="identityDisplayName,identityName">
<AfterScript>
<Source>
assimilateWorkItemApprovalSet(wfcontext, item, approvalSet);
</Source>
</AfterScript>
<Arg name="approvalSet" value="ref:approvalSet"/>
<Arg name="workItemDescription" value="Batch Request Approval requested by $(launcher)"/>
<Arg name="workItemElectronicSignature" value="ref:batchApproverElectronicSignature"/>
<Arg name="workItemIdentityRequestId" value="ref:identityRequestId"/>
<Arg name="workItemNotificationTemplate" value="ref:batchApproverEmailTemplate"/>
<Arg name="workItemPriority" value="ref:workItemPriority"/>
<Arg name="workItemRequester" value="$(launcher)"/>
<Arg name="workItemTargetClass" value="sailpoint.object.BatchRequest"/>
<Arg name="workItemTargetId" value="ref:batchRequestId"/>
</Approval>
<Description>
If approvalScheme contains batchRequest and the batchRequestApprover is
non null this step will send items with decisions and comments
from the cart for final decision.
</Description>
<Transition to="end"/>
</Step>
<Step icon="Stop" name="end" posX="920" posY="1"/>
</Workflow>