Hello all, Stephen here again — I’m a writer for SharePoint Designer. I’d like to tell you about a fix that was included in Service Pack 2 for Office SharePoint Server 2007 and Windows SharePoint Services 3.0. This fix affects workflows designed in SharePoint Designer 2007. Then I’ll show you how to intentionally create a workflow loop by using two workflows instead of one.
Before Service Pack 2, it was too easy to inadvertently design a workflow that triggered itself and created an infinite loop. For example, consider this scenario:
1) A workflow starts when an item is changed.
2) The workflow updates (or changes) the current item (e.g. by using the Set Field in Current Item action).
3) Because the workflow changes the item, it triggers itself.
So if you had an on-change workflow that sends you an e-mail and then updates the current item, you could quickly receive several hundred e-mails in your Inbox.
After you install Service Pack 2 on your server, it is no longer possible for a workflow that starts when an item is changed to trigger itself by changing/updating the current item. This infinite-looping scenario is not possible:
Many people, however, have designed workflows that actually leverage infinite looping. For example, you could design an on-change workflow that loops endlessly on a task item and that sends a daily reminder until that task is marked complete. The workflow triggers itself by updating a Counter column that was added to the list just for this purpose. And the workflow has a rule that stops or “short circuits” the workflow if some condition is satisfied — in this case, the workflow stops without changing the current item if the task Status = Completed. After SP2, this workflow will in effect be broken because it cannot trigger itself.
SP2 does not block infinite loops, which can be useful, but to re-create what worked before you must design two (or more) on-change workflows that trigger each other. Two on-change workflows that trigger each other by updating/changing the current item is a “co-recursion” scenario:
In addition, it is very common to implement a state-based workflow by using several shorter workflows that trigger each other. For example, you might have a list with a Status field and several on-change workflows attached to that list. All of those workflows include a step at the end that updates the Status field. So one workflow triggers several others by updating the Status, and then those workflows look at the value in the Status field to determine whether they should continue running or stop. This state-based workflow is also a “co-recursion” scenario because one workflow starts many other on-change workflows by changing/updating the current item. Service Pack 2 does not block this type of state-based workflow that relies on co-recursion.
· Before SP2, a single on-change workflow could enter an infinite loop by updating the current item, thus triggering itself.
· After SP2, an on-change workflow can trigger any other on-change workflows by updating the current item, but an on-change workflow cannot trigger itself. So co-recursion scenarios -- including any scenario that implements a state-based workflow by using many smaller on-change workflows -- are not blocked.
· As a reminder, it has never been possible to create an infinite loop by having an on-create workflow create an item in the current list. Every workflow has a property that contains the “workflows I cannot start” — this property is used to prevent looping for workflows that start when an item is created.
· As a further reminder, all of the previous scenarios involve only workflows attached to a single list or library. Infinite looping in cross-list scenarios has never been blocked for either on-change or on-create workflows.
This section presents an example of how a single on-change workflow could leverage infinite looping before SP2. After SP2, this workflow will not trigger itself, so the next section presents an example of how to create a loop by using two separate workflows.
Assume you have a task list named Team Tasks, and you want to design a workflow that will send a reminder every day until the task is marked complete.
First, add a column named Counter to the list with a default value of 0.
You need to hide the Counter columns from the list forms (New Item, Edit Item) so that only the workflow can access/update it. Fist, on the list settings page, click Advanced Settings, and then allow the management of content types.
On the list settings page, click each content type, and on the next page click the Counter column. Make the Counter column hidden. Do this for every content type in the list.
After creating and hiding the Counter column so that it does not appear in forms, you’re ready to design the workflow.
The Daily Reminder workflow should start whenever an item is created or changed.
The first step checks for two things: (1) If the task has already been marked complete, the workflow stops. This rule “short-circuits” the loop whenever the task is finally marked complete. (2) If the task is not completed, the workflow checks to see if the due date is in the future (greater than today). If this is true, the workflow pauses until the due date, because you don’t want to send reminders until the due date has been reached.
The second steps again checks whether the task is completed (in case the workflow paused until a due date on the previous step, and the task was completed in the interim). If the task is still not complete, the workflow pauses for one day.
The third step again checks to see if the task was completed while the workflow was paused; if true, the workflow stops.
If the task has not been completed, the workflow (1) sends the e-mail reminder; (2) set the CurrentCount variable by doing a lookup to the Current Item/Counter field; (3) adds 1 to CurrentCount and stores this value in a NewCount variable; and (4) sets the Counter column to the value stored in the NewCount variable.
Basically, this step increments the Counter column by 1 each time the workflow runs, so you can look at the Counter column to see how many reminders have been sent. And most importantly, the “Set Field in Current Item” action at the end of this step is what “changes” the current item, thus causing the workflow to trigger itself and create the loop.
After SP2, you can still achieve this looping effect, but it requires designing two workflows that trigger each other (co-recursion) instead of a single workflow that triggers itself.
Here you’ll use a (1) Counter workflow that increments the count and a (2) Worker workflow that actually sends the reminder mail.
As above, you need to create a Counter column in the list with a default value of 0, allow the management of content types, and make this field hidden for every content type in the list.
This two-workflow design requires a second column, SendMail, which will act as a flag for the Worker workflow. The default value must be No – otherwise, any change to a task item would cause the reminder mail to be sent.
The Counter workflow will start when an item is created or changed.
The first step checks the task status – if the task is complete, the Counter workflow stops.
If the task due date is in the future (greater than today), the second step pauses until the due date, because you don’t want to send reminders until after the task is due.
The third step again checks for task completion, in case the task was completed while the workflow was paused on the previous step. If the task is still not complete, the workflow pauses for one day.
The final step checks the status again to see if the task was completed during the previous day-long pause. If not, the workflow updates the current item by (1) incrementing the value of the Counter column by one and (2) setting the SendMail flag to Yes (the default value is No).
The Counter workflow above ends by updating (changing) the current item. These updates trigger the Worker workflow, which is set to start when an item is changed.
The Worker workflow simply checks to see if the SendMail flag is set to Yes; if true, the workflow sends the reminder message and sets the flag back to No.
Setting the SendMail flag to No is the change that triggers the Counter workflow above. The Counter and Worker workflows will trigger each other, sending daily reminders until the task is marked complete.
Alternatively, instead of an infinite loop, you can have the Worker workflow escalate the task notification when the Counter column reaches a certain value — say 5 reminders. The following step executes different branches depending on the reminder count. When the count reaches 5, the workflow sends a message to a manager, whose e-mail address you can either “hard-code” into the Send an Email action or retrieve from a list by using a workflow lookup.
You could also have the Worker workflow reassign the task to a different individual or group after a certain number of reminders have been sent. For this step, the workflow reassigns the task to a SharePoint group comprised of team members who are responsible for following up on such escalated tasks.
If you want to end the loop when the count reaches a certain number, also make sure to add a branch to the first step of the Counter workflow – not the Worker workflow. This branch stops the loop when the Counter column reaches 6.
I hope you find this useful.
Thanks so much for posting this. I was pulling out hair trying to work out why my (deliberate) recursive workflow was not firing a second time.
Why are these service pack "fixes" not documented, for example in the list of changes linked to on this page;
First of all thank you so much for sharing this information with the community. I have no doubt it will save many people hours of frustration trying to understand what has been changed with a relatively easy to implement (and well articulated) solution.
However I was wondering if you could provide a bit more information as to why this change was made. I know a considerable number of businesses and business users impacted by this change and while over time they can resolve it, it would be really nice to have more explanation for the motivation behind a change of this magnitude.
The initial reason described sounds more like a training, logic, and user issue instead of a technology one. However this might be me misinterpreting the message.
My concern is: In most scenarios complicating the process increases training, decreases user adoption, and makes the entire situation more difficult to manage, so it would really help/be appreciated to have more 'business' or 'technical' reasoning behind why this change was made/is so important. (Otherwise it might be hard to convince many businesses to switch to SP2 - if business users have to re-work/re-do many of their existing workflows made in SPDesigner).
Thank you in advance for any response,
Thanks this is helpful.
Do you know if there is any impact to workflows that start when a new item is created, or more specifically when the item in a list is created by a COMMIT from a SharePoint Designer form?
I wanted to know the following:
i. On item create, email sent to xyz.
ii. Xyz checks the list item and keys in information from him. This will be done by a new set of fields in the same list item. Should have mandatory fields for the xyz user.
iii. Xyz completes and submits.
iv. On submission another user receives and sees another set of information. S/he keys in the information and proceeds to submit.
v. This process repeats until the workflow ends.
Basically, there are a set of users who see different columns based on access control. Is this possible?
Re: Richard's questions about the motivation behind the change: Workflows that do not automatically restart itself is actually one of our most frequently requested fixes and top support issues, for both functionality and server health. The infinite loop prevents the ability to create common, simple workflows that modify status or change fields on the item in its completion cycle. Infinite loops that are not designed to terminate are actually harmful to the system (e.g. the flooding inboxes, or an infinite loop that creates items indefinitely; all will eat system resources to run), and a lot of people create these infinite loops without realizing it, because they think of a change to the item as just part of the logic inside the running instance, not something that will cause it to run again and again.
So the fix is really there to make simple, most common case work as expected and prevent inadvertent infinite loops that are unintentionally harmful. You could think of the ability to create infinite loops in a single workflow as a bug or "loop" hole;) that you could leverage to work around not being able to insert loops directly in SPD (note: the accidental attacks are also why SPD doesn't have looping to begin with). We knew there would undoubtely be power users who would have intentional loops designed to terminate correctly, so we made sure the fix would provide a workaround the correction by doing what this describes to get around it.
I hope this helps clarify why this is in place.
re: trockwell's question, this does not impact item creation or modifying items outside of the workflow. It's only impacted when the workflow itself updates the item.
re: Josephine's question: there is no column level acls as far as I know, but you can create separate views for different people and potentially send them notifications with different links to the views that are appropriate for them.
Thanks for the post. After reviewing this, I realized that there is one problem with this solution that is not mentioned. This is, if the user created his list with the "automatic email" sent to the "Assigned To" for any changes to the list, implementing these two recursive workflows will trigger two (2) background emails to be sent to the "Assigned To" for each updates in the two workflows - one for the counter update, and one for the SendMail update, won't it?
Can I consolidate all the tasks and send one email, instead of sending one email to each task? How can I achieve this?
We don’t use recursive workflows intentionally – obviously if a workflow starts on change of an item and then changes something in that item it used to recur and we had to check that so it didn’t loop. So if SP2 is stopping this it should be quite good for us.
However the error messages SharePoint produces in the log file are very annoying as they make monitoring of workflows very difficult – do you know of a stopping them being produced?
I did every thing above, Howerver i receive this error after the second pause.
"The e-mail message cannot be sent. Make sure the outgoing e-mail settings for the server are configured correctly."
First pasuse: Email is sent
Second Pause: Shows the error above
Third Pasuse: Email is sent
Fourth Pause: Shows the error above
Fifth Pause: Email is sent
Please, help me
Does anybody is be able to get Today column calculated this --> [created]+[count] , and then this get update everytime the workflow counter get update and then send the reminder email by comparing
duedate is equal to Today
send email [analyst]
Nice post... it is giving me light but ...Could you provide more information about how you make'Today' Column get updated dynamically? (I am assuming 'Today' column type calculated such as =[created]+[counter])
I am actually having the exact opposite problem (on Service Pack 1). I have a workflow that does a calculation, sets a field to the new value and sends an email to the end user. The problem is the end user can change the values that go into the calculation, so I need it to recalculate each time someone edits that item. However, as soon as you set the field, a new instance of the workflow beings because the item was changed. In this workflow it does the calculation again and sends the e-mail, but because it did the calculation - and did anoter "Set" - the item has now changed, thus creating an infinite loop.
So. I'm verrrry happy they have this fixed in SP2, but it's very difficult to get SP2 through change control this year, so I'm looking for a way to prevent the loop.
My next step is to create a 2nd list and store several values from the 1st list. Then I will compare values in List A to values in List B in the workflow. If nothing has changed, the workflow will stop before it updates any values. This should solve my problem, but seems like a tedious workaround.
Any other suggestions?
We are experiencing some issues with workflows not starting on a document library which has been e-mail enabled. I can imagine that the change you described also causes this issue, am I correct?
Is this also true for e-mail enabled folder? We are experiencing some issues with workflows not start when a new items is added via e-mail on an e-mail enabled library.
Have a look at this earlier post from Darren on "Workflows and user context":
See esp. this paragraph -- do you need to do this on your server?
"In the SharePoint Infrastructure public update box administrators can allow email enabled lists to trigger workflows as the last person to save the workflow when an item is created via email. Run “stsadm.exe –o setproperty –propertyname declarativeworkflowautostartonemailenabled –propertyvalue yes” on the patched server to enable this."