Why every branch has to produce the same output

When you tick Enable outputs on a Branch on Conditions step, later steps read the branch's result through the branch step's own reference name, and they cannot know in advance which branch ran. So every IF branch and the ELSE branch must hand on the same output names with the same data types. Workday's component reference says it in one line: if you enable outputs, make sure each branch's output data type is the same. The Orchestrate course manual adds the names: each branch must return the same output names and types.

What a branch "returns" follows the rule for groups. Workday's Group Steps page says a group is treated as a single logical entity and only the data output by the last step in the group is available downstream. In the app source, each branch of a Branch on Conditions step is stored as a group of steps, and Workday's sample apps behave accordingly: the last step of each branch is what the branch hands on. A branch that ends in a Send HTTP Request on one side and a Log step on the other has two different outputs, which is exactly what the reference tells you to avoid. Orchestrate uses strong data types and checks type assignments at design time, so the place to fix it is the end of each branch, not the step that reads the result.

Do you need Enable outputs at all?

Enable outputs is only for when steps after the branch need data the branch produced. Many branches only do work, such as writing a record on one side and logging a skip on the other, and nothing downstream reads their result. In that case leave Enable outputs off and the matching rule does not apply. Many of the branches in Workday's published sample apps run with it switched off.

If only a value differs, and not the steps, you may not need a branch either. Expression Builder lets a property's value be conditional: you define the condition, then use If conditions are true and If conditions are false to give the value for each case. A Create Values step whose endpoint value is conditional is simpler than a branch whose only job is to pick one of two URLs.

How to balance the branches with Create Values

When you do need outputs, end every branch with a Create Values step that sets the same keys with the same types. The Extend course manual gives the same tip: put a Create Values step on both sides of the branch with the same names.

Take an Equipment Request orchestration that must find the approver differently for managers and for everyone else, and then use the approver afterwards.

Branch Steps Last step (Create Values)
BranchIF the requester is a managerStepsSend Workday API Request for the manager's managerLast step (Create Values)approverId (String) = the WID from the response, routed (Boolean) = true
BranchELSEStepsnone neededLast step (Create Values)approverId (String) = "", routed (Boolean) = false

After the branch, any step reads data.FindApprover.approverId and data.FindApprover.routed, where FindApprover is the Branch on Conditions step's reference name. Workday's samples read branch outputs exactly this way, for example data.WQLData.response after a branch whose two paths each end in a Send Workday API Request, one using POST and one using GET. Because both ends are the same kind of step, both hand on a response of the same type, which is the other way to balance a branch.

Three details break the match:

  • Names must be identical. Spell each key the same way on every branch; approverId on one side and approverID on the other is not a matching pair.
  • Types must match, not just names. An empty string is a String; 0 is a Number. If one side carries XML from a response, the other side must carry XML too. One Workday sample builds a placeholder with a Create Text Template set to application/xml, and another casts a literal with asXML(), so the ELSE side still hands on an XML value. Another sample names its padding step CreateTextTemplateOnlyUsedToMatchTheOutputOnTheOtherBranch.
  • Every extra IF branch counts. Branches added with Add Branch each need the same closing step. Orchestrate evaluates branches from left to right and runs only the first one whose condition is true, and any branch can be the one that runs.

Do not try to read a step inside a branch directly from outside it. The group rule makes only the last step's output visible, so data.GetManagersManager.response is not something you can count on after the branch has finished. Copy what you need into the closing Create Values.

When Continue on Conditions is the better choice

Branch on Conditions is for two paths that both carry on. If one path really means "stop, this input is wrong", use Continue on Conditions instead. It takes one or more assertions and a message for each. If the assertions evaluate to true the orchestration carries on; if not, the orchestration stops and Orchestration Builder logs your message. There is no second branch to balance.

The two combine well. A Workday sample routes an inbound request by content type with Branch on Conditions, Enable outputs on: each supported type's branch ends in a Create Values with the integration parameters, and the ELSE branch ends in a Create Values that sets the same keys to empty values. The very next step is Continue on Conditions with an assertion along these lines:

data.RouteRequest.integrationSystemId.isEmpty().not()

and a message such as "Unsupported request format". The branch stays balanced, and the unsupported case stops with a clear reason in the log rather than running on with empty values.

The message is itself an expression, so it can include the data that caused the stop. Another sample stops after a failed call with the assertion data.PostRequest.responseStatusCode.is2xxStatusCode() and a message that appends the status code.

Continue on Conditions is available in the Synchronous, Asynchronous, Business Process, Home Card, Integration System and Custom Agent Action templates, the same list as Branch on Conditions. Branching is meant for light routing; the Extend course manual points to Workday Studio when an integration needs complex error handling. Orchestrate logging covers making a stop visible to whoever reads the run.

How to prove the branches are balanced

Click Validate; the step should raise no type or reference errors. Then confirm the output at run time with the step debugger: select the Branch on Conditions step, choose Debug Step, connect to a tenant where the app is deployed and run it with inputs that send it down each branch in turn. Debug Outputs should show the same keys and types whichever branch ran. Integration System orchestrations must be deployed and run once on the tenant before they can be debugged, and the debugger cannot run Trigger Business Process, Trigger Integration, Trigger PDF Generation or polling Send HTTP Request steps, so a branch containing one of those is checked from the run logs instead. Finally, run the deployed orchestration once down the ELSE path and check that the step after the branch received the values you set there, not an empty or failed reference.

Sources checked