Status rollback after transition

I've an intermittent trouble when doing a transition in an issue parent.
There is a post function that solves the subtasks and this action is occurring normally.
However, sometimes the parent issue is transitioned but your status back to the previous.
In the history and transitions tab panels I can see that issue is in the final status which it should is.
There is no information in history or log that indicates what is happen.
I assume that is a possible rollback, but nothing is thrown in the log file.

To clarify, the issue below is in 'PRONTO PARA EXPEDIÇÃO' status.


Sem título.png



But seeing the moviments, it should to be in 'EXPEDIDO' status.

There isn't in the workflow a transition that leaves status back on this way.


Someone have any ideia how to fix this?



2 answers

Hi Mário dos Santos,


Do you have the code for the post-function that I can look at please?




Currently, I'm using it into a listener to reuse in others workflows.

But even though using it in the listener, the blinking continues.

The rate of this failure is more or less one for every 200 issues processed.


import groovy.json.JsonOutput
import com.atlassian.jira.issue.*
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.Attachment
import com.atlassian.jira.issue.fields.*
import org.apache.commons.codec.binary.Base64
import groovy.json.JsonSlurper
import groovy.json.JsonOutput 
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.user.ApplicationUser

class Global {
    static String baseUrl = ComponentAccessor.getApplicationProperties().getString("jira.baseurl")
    static String urlAddTags = baseUrl+'/rest/scriptrunner/latest/custom/addTagsToZendesk?'
    static String urlGetAttachmentToken = baseUrl+'/rest/scriptrunner/latest/custom/getTokenForLastAttachment?'
    static String urlSendAttachment = baseUrl+'/rest/scriptrunner/latest/custom/sendAttachment?'
    static String urlAddComment = baseUrl+'/rest/scriptrunner/latest/custom/addComment?'
    static String cfTicket = "customfield_11086"
    static String cfNomeCliente = "customfield_11071"
    static String cfEndCentralDownloads = "customfield_11054"
    static String tipoContrato = "customfield_11037"

def issue = event.getIssue()

def commentManager = ComponentAccessor.getCommentManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

CustomField cfTicket = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(Global.cfTicket)
CustomField cfNomeCliente = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(Global.cfNomeCliente)
CustomField cfEndCentralDownloads = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(Global.cfEndCentralDownloads)
CustomField tipoContrato = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(Global.tipoContrato)

def ticket = issue.getCustomFieldValue(cfTicket) as String
ArrayList contratos = issue.getCustomFieldValue(tipoContrato) as ArrayList
def nomeCliente = issue.getCustomFieldValue(cfNomeCliente) as String
def endCentralDownloads = issue.getCustomFieldValue(cfEndCentralDownloads) as String
def issueKey = issue.getKey()

if (ticket != null && nomeCliente != null) {
    ticket = ticket.replace("]","")
    ticket = ticket.replace("[","")
    String commentValue
    commentValue = "Olá " + nomeCliente + ",\n\n" +
    "A Release Oficial foi expedida e publicada na Central de Downloads.\n" +
    "O pacote pode ser acessado no endereço: " + endCentralDownloads
    //Adiciona comentário no JIRA
    commentManager.create(issue, user, commentValue, false)
    //Adiciona comentário no Zendesk
    addComment(issueKey, ticket, commentValue)
    def outputTAG
    if (contratos != null) {
        for (int i = 0; i <= contratos.size(); i++) {
            if (contratos[i].toString() == "CLOUD") {
                outputTAG = "tags=exp_cloud&tags=exp_def&tags=jira_issue_resolvida"
        if (outputTAG==null) {
            outputTAG = "tags=exp_def&tags=jira_issue_resolvida"
        addTag(issueKey, ticket, outputTAG)

def issueService = ComponentAccessor.getIssueService()
def userManager = ComponentAccessor.getUserManager()
ApplicationUser userAdmin = userManager.getUserByKey("integrador.jira")

if (!issue.isSubTask()) {
    def subTasks = issue.getSubTaskObjects()
    subTasks.each {
        if (it.getStatus().name == "Associado") {
            def issueInputParameters = issueService.newIssueInputParameters()
            def actionID = 131
            def validationResult = issueService.validateTransition(userAdmin,, actionID,issueInputParameters)
            if (validationResult.isValid()) {
               def issueResult = issueService.transition(user, validationResult)
               if (! issueResult.isValid()) {
                   log.warn("Failed to transition subtask " + it.key + " errors: " + issueResult.errorCollection)
            else {
                log.warn("Could not transition subtask " + it.key + " errors: " + validationResult.errorCollection)

Object addTag(String issueKey, String ticket , String tags) {
    URL url = new URL(Global.urlAddTags + 'issueKey=' + issueKey + '&ticket=' + ticket + '&' + tags)
    HttpURLConnection conn = (HttpURLConnection) url.openConnection()
    def sb = new StringBuffer()
    def is = new BufferedInputStream(conn.getInputStream())
    def br = new BufferedReader(new InputStreamReader(is))
    def inputLine = ""
    while ((inputLine = br.readLine()) != null) {
    return new JsonSlurper().parseText(sb.toString())

Object addComment(String issueKey, String ticket, String commentValue) {
    def urlString = Global.urlAddComment + 'issueKey=' + issueKey + '&ticket=' + ticket + '&commentValue=' + URLEncoder.encode(commentValue, "UTF-8")
    URL url = new URL(urlString)
    HttpURLConnection conn = (HttpURLConnection) url.openConnection()
    def sb = new StringBuffer()
    def is = new BufferedInputStream(conn.getInputStream())
    def br = new BufferedReader(new InputStreamReader(is))
    def inputLine = ""
    while ((inputLine = br.readLine()) != null) {
    return new JsonSlurper().parseText(sb.toString())

Ok and do you get an error on the times that it fails?

No, nothing falls on atlassian-jira.log file around the transition time.

I think can be a bug in JIRA or Scriptrunner maybe.

I'm able to reproduce this exact behavior making a simple script post function like this:

def subTasks = issue.subTaskObjects
subTasks.each { subTask -> 

// Here, make a transition


// Here, updating the issue and making external update

When I leave the transitions on subtask by last, like below, the bug go away.


// Here, updating the issue and making external update

def subTasks = issue.subTaskObjects
subTasks.each { subTask -> 

// Here, make a transition




But, it isn't the case of my Script, else it would fail every time.


Could you test the above condition to rule out a possible problem in my environment, please?

The transition code seems to work fine for me. You say the error where the parent task is left in it's previous status only happens once ever 200 times on average? This might suggest that it is something on the issue that is causing it to fail. Have you looked for trends accross the issues that it is failing for?

Also, which version of JIRA and ScriptRunner are you using?

It seems like this might be a known issue with the IssueService, it might be best to user IssueManager and do issue.setStatus() on the issue then do issue.updateIssue(). This should correctly set the status if the transition fails.

I'm using JIRA 7.1.2 and ScriptRunner 4.3.16

About the trends on fail issues I didn't find apparent similarity.
I was suspecting the number of subtasks (in some cases with 400 or more). But there were parent failure with 30 subtasks, for example.

For the suggestion to use IssueManager instead IssueService, would you think the problem is in update the subtasks?

Because in that scenario, all subtasks are updated correctly. The even problem is in the parent issue. In this way, the update of the status is being doing by standard workflow post functions (only with the mentioned listener like last in list).

Therefore, the listener runs transitioning all subtasks and finishes. The JIRA makes the transition (or, in that case, it doesn't get to do it completely until the end).

The curious thing is that everything seems to happen correctly because it records the history, transitions, comments and after that the problem occurs.

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Posted yesterday in Jira

We want to know what Jira Service Desk apps you're using!

Hi Community! My name is Amir and I’m on the Jira Service Desk product marketing team at Atlassian. Our team would love to understand how you’re leveraging our ecosystem for Jira Service Desk. Wha...

40 views 0 5
Join discussion

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you