Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Why is JIRA saying that a perfectly valid transition for my issue is invalid?

aware74 December 6, 2011

I am using the following instructions to automatically transition an issue sub-task of type "Application CR Sub-Task" (CR stands for Change Request for the curious) from "Awaiting Approval" to "Start Review":

https://developer.atlassian.com/display/JIRADEV/Performing+Issue+Operations

(see "Transitioning an existing issue")

I am attempting to execute this logic in response to the IssueEvent.ISSUE_CREATED event for the above issue type, using the following instructions for creating an event listener:

https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Writing+event+listeners+with+the+atlassian-event+library

When executing the necessary transitioning logic, however, I get the following error message:

It seems that you have tried to perform a workflow operation (Start Review) that is not valid for the current state of this issue (TINT-89). The likely cause is that somebody has changed the issue recently, please look at the issue history for details.

This didn't make any sense to me, though, because right before this error message being returned from the validation of my transition, I echoed out the following to the log:

[INFO] [talledLocalContainer] 2011-12-07 11:52:56,295 http-2780-2 DEBUG admin 712x4862x1 nz4t4g 127.0.0.1 /secure/CreateIssueDetails.jspa [plugins.issue.transition.IssueTransitioner] issue == TINT-89, transitionName == Start Review, loggedInUser == admin, issueId == 10727, actionId == 11, issueStatusId = 10000, issueStatusName = Awaiting Review, nextActionId == 191, nextAction == null, nextActionXml == null

So the issue is in "Awaiting Review" state (id 10000), and all I'm trying to do is to execute the "Start Review" action (id 11), which according to the Workflow's own XML, is a valid action id for that state id:

<step id="1" name="Open">
      <meta name="jira.status.id">10000</meta>
      <actions>
<common-action id="2" />
        <action id="11" name="Start Review">
          <meta name="opsbar-sequence">20</meta>
          <results>
            <unconditional-result old-status="Finished" status="Underway" step="2">
              <post-functions>
                <function type="class">
                  <arg name="field.value"></arg>
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueFieldFunction</arg>
                  <arg name="field.name">resolution</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.AssignToCurrentUserFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.UpdateIssueStatusFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.misc.CreateCommentFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.GenerateChangeHistoryFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.issue.IssueReindexFunction</arg>
                </function>
                <function type="class">
                  <arg name="class.name">com.atlassian.jira.workflow.function.event.FireIssueEventFunction</arg>
                  <arg name="eventTypeId">11</arg>
                </function>
              </post-functions>
            </unconditional-result>
          </results>
        </action>
      </actions>
    </step>

So I went a little deeper into how that error message gets generated and discovered that DefaultIssueService.validateTransition() -> IssueUtilsBean.isValidAction() -> IssueUtilsBean.loadAvailableActions() -> AbstractWorkflow.getAvailableActions(issueObject.getWorkflowId(), inputs) for the issue in question returns an empty array of action IDs because the WorkflowEntry that corresponds to the issue's workflow ID is still in a CREATED state, not an ACTIVATED state. I had to create extensions and/or wrappers for both IssueUtilsBean and Workflow to find this out, because I couldn't get either to log its output.

Anyways, what I want to functionally achieve is to perform a valid workflow action on an issue once it is created *and* once the WorkflowEntry corresponding to the workflow ID of the issue is actually ACTIVATED.

If the way to accomplish this is not an EventListener that listens for IssueEvent.ISSUE_CREATED events, because at that point, the workflow entry behind that issue is not yet active, what is the appropriate way? Implement a com.opensymphony.workflow.util.WorkflowListener? Is there an example for how to do this appropriately in a JIRA 4.4.x environment?

Thanks,

Mike

6 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

3 votes
Answer accepted
aware74 December 19, 2011

The only way around this for now is to perform the transition yourself after you create the issue, and not delegate the logic to a listener that responds to an ISSUE_CREATED event, because at that precise moment, the workflow entry for the issue is still not activated.

I have additionally asked Atlassian to consider an enhancement request that would allow developers to register listeners to be notified when workflow entries associated with issues change state.

9 votes
Ilia Ostroumov December 24, 2015

use this code to activate workflow entry in your listener before transition:

List<GenericValue> workflowEntries = ComponentAccessor.getOfBizDelegator().findByAnd("OSWorkflowEntry", FieldMap.build("id", issue.getWorkflowId()));
for (GenericValue workflowEntry : workflowEntries) {
    if (workflowEntry.getInteger("state") == null || "0".equals(workflowEntry.getInteger("state").toString())) {
    workflowEntry.set("state", new Integer(WorkflowEntry.ACTIVATED));
    workflowEntry.store();
    }
 }
Yanduganov Andrey August 14, 2017

Thank you so much! I looked for this more than month. It's a real solution.

Like Ilia Ostroumov likes this
Thanos Batagiannis _Adaptavist_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 23, 2017

Brilliant. Unfortunately I have only one vote.

Thanks

Like Ilia Ostroumov likes this
Alysson Bispo Pereira January 29, 2018

I have the same strange problem. But, every time a got:

 

java.lang.UnsupportedOperationException: We don't currently index workflowid - can't get it from document

 

when I try to use:

List<GenericValue> workflowEntries = ComponentAccessor.getOfBizDelegator().findByAnd("OSWorkflowEntry", FieldMap.build("id", issue.getWorkflowId()));

Ilia Ostroumov January 29, 2018

I am not sure, but this may happen in case if your issue is type of Issue instead of MutableIssue

1 vote
Laszlo Kremer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 12, 2014

I had the same problem, but sorted out by using the Script Runner Plugin's feature: added a Script Post-function to the Create transition of the workflow, called the Fast-track transition an issue. Entered a condition which would start the transition, selected the transition, and it works nicely. Don't forget to move the post function below the Fire Event post function.

HomeAway
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 22, 2015

We can't get fasttrack to work with two stacked, mutually exclusive conditioned PFs. Set after the create event in precedence.

0 votes
Jared Lynem October 6, 2015

My way around this was to create a separate thread to do the transition, after waiting a few seconds.  This gives the workflow process time to activate the new instance.  It's hacky for sure but it works the way you would expect.

Sergei Meranovich November 5, 2015

Could you please give more details on this? Do you create a thread to call issueService.transition(user, validationResult)?

0 votes
Deon Heyns September 16, 2013

I am answering this here so that if anyone (me included) runs into this we have some idea on how to solve it. So here is what I done to solve it.

  1. Move the "Fire a Issue Created event that can be processed by the listeners." post function to the end of the list
  2. Add a "Re-index an issue to keep indexes in sync with the database." post function as the second item in your post functions
  3. Create your new sub-tasks / issues

This works for me YMMV.

Adam S. February 28, 2017

This appeared to work for my login (as a JIRA admin). But for some reason didn't work for other service desk agents in the team. After tinkering a bit (including adding a post function to the transition to "Set issue status to the linked status of the destination workflow step"), I eventually found that I needed to set the automation task to run asynchronously. As I had other automation tasks that ran for certain agents, I also had to set these to run asynchronously. I don't know why this worked, but it did. Only setting 1 to async didn't work. It had to be both. The other automation task only changed a custom field in the issue as well and it wasn't status related.

0 votes
MattS
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 8, 2011

Do you have conditions or a validator involved in that step? Probably need to see some code of how you're making the transition.

~Matt

aware74 December 8, 2011

No conditions on the Create Issue transition. Just a permissions validator to make sure the user has Create Issue permisison. There are no conditions or validators on the "Start Review" transition.

Here is the code I'm using to make the transition:

public ErrorCollection transition(Issue issue, String transitionName) throws IssueTransitionException {
      ErrorCollection errors = null;
      User loggedInUser = getAuthnCtxt().getLoggedInUser();
      Long issueId = issue.getId();
      int actionId = WorkflowUtils.getActionId(transitionName, issue, getWorkflowMgr());
      Status issueStatus = issue.getStatusObject();
      String issueStatusId = issueStatus.getId();
      String issueStatusName = issueStatus.getName();
     
     
      IssueInputParameters issueInputParams = new IssueInputParametersImpl();
      issueInputParams.setAssigneeId(getAuthnCtxt().getLoggedInUser().getName());

      TransitionValidationResult transValidationResult = getIssueSvc().validateTransition(loggedInUser, issueId, actionId, issueInputParams);

      if (transValidationResult.isValid())
      {
         IssueResult transitionResult = getIssueSvc().transition(loggedInUser, transValidationResult);

         if (!transitionResult.isValid())
         {
            errors = transitionResult.getErrorCollection();
         }
      }
      else
      {
         errors = transValidationResult.getErrorCollection();
      }
      
      return errors;
   }

aware74 December 8, 2011

And here is the logic in AbstractWorkflow.getAvailableActions() that's causing no actions to be returned because, apparently, the created issue is still associated with a workflow entry that is only created, not activated:

public int[] getAvailableActions(long id, Map inputs) {
        try {
            WorkflowStore store = getPersistence();
            WorkflowEntry entry = store.findEntry(id);

            if (entry == null) {
                throw new IllegalArgumentException("No such workflow id " + id);
            }

            if (entry.getState() != WorkflowEntry.ACTIVATED) {
                return new int[0];
            }

            &lt;snip&gt;
        } catch (Exception e) {
            log.error("Error checking available actions", e);

            return new int[0];
        }
    }

I verified by extending this class, overriding getAvailableActions(), and adding logging that this method is returning an empty array because entry.getState() == WorkflowEntry.CREATED.

AkashD August 7, 2016

How to solve this using SIL post function I am getting the error 

jjupin.JPG

 

And my script is 

string li;
bool alldesign = true;
//we should have here a do - while, but this will work for the sake of the example
for (li in linkedIssues(parent.key)) {
if (%li%.status != "Design Completed" && li != key) {
alldesign = false;
}
}
if(alldesign) {
autotransition("Design Completed", parent.key);
}

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events