Example Conditions and Validators
The Jira expression examples highlighted in this section can be used for either conditions or validators and on all transitions unless noted otherwise.
Jira expression framework limitation: nested condition
Jira expressions do not support nested if statements. For example, the following expression will fail:
if (issue.summary.length > 10 ) {
if(issue.assignee) {
// ...
}
}You can instead combine this into a single expression, as shown in the example below:
if (issue.summary.length > 10 && issue.assignee) {
// ...
}Atlassian's new transition experience in Jira is being permanently rolled out in April 2025. As a consequence, how your Jira expressions (conditions and validators) work will change. Check out our Breaking Changes section for more information.
Checks if the issue has been in a status previously
issue.changelogs.some(c =>
c.items.some(i => i.toString == 'In Progress')
)Comments
All comments have a minimum length:
issue.comments.every(comment => comment.body.plainText.length > 10)All existing comments must be public (for Jira Service Management):
issue.comments.every(c => !c.properties["sd.public.comment"].internal)If there is a comment on transition, it must be an internal comment (note that the `internal` property is a string during transition!):
issue.comments.every(c => c.id != null || c.properties["sd.public.comment"].internal == 'true')Require a comment during transition:
issue.comments.some(comment => comment.id == null)Current logged-in user has added at least one comment
issue.comments.some(c => c.author.accountId == user.accountId)Date comparison
The following system fields return a Date object: created, update, and resolutionDate.
Checks whether a date custom field is 30 days or more in the future from today's date:
issue.customfield_10200 ?
new CalendarDate(issue.customfield_10200) >= new CalendarDate().plusDays(30) :
falseDate time custom fields have a string value, but can be converted to a date time like so: new Date(issue.customfield_10217)
Checks whether a date time custom field is less than 6 hours in the future:
issue.customfield_10217 ?
new Date(issue.customfield_10217) <= new Date().plusHours(6) :
falseChecks whether an issue is due within the next 3 months:
The following system fields return a CalendarDate object: dueDate.
issue.dueDate ?
issue.dueDate <= new CalendarDate().plusMonths(3) :
false
Caution:
dueDate and resolutionDate, along with custom fields, can be null. Always check for null values before performing operations on them.
Date custom fields have a string value, but can be converted to a calendar date like so: new CalendarDate(issue.customfield_10200)
Checks whether an issue was created more than 7 days ago:
issue.created < new Date().minusDays(7)Checks whether an issue was resolved within the last 30 days:
issue.resolutionDate ?
issue.resolutionDate >= new Date().minusDays(30) :
falseChecks whether an issue was updated within the last 2 hours:
issue.updated > new Date().minusHours(2)Description field must contain more than 30 characters
issue.description.plainText.length > 30Field is not empty
The following examples check the field is not empty (that is, it's a required field).
At least one of two label fields must have a value:
Checks if the issue type is Bug or Task:
["Bug", "Task"].includes(issue.issueType.name) Require a comment during transition:
issue.comments.some(comment => comment.id == null)Field(s) changed
Check whether a specified field has been changed in the issue's lifetime.
issue.changelogs.some(c => c.items.some(i => i.field == 'Field Name'))Field(s) required
For text fields, single, multi selects, and radio buttons, checkboxes, and cascading select fields:
issue.customfield_10040 != nullFor cascading select field:
// for parent value
issue.customfield_10266?.value != null
// both parent and child (you cannot set the child without the parent)
issue.customfield_10266?.child?.value != null This example checks that a text field (possibly supporting rich text) is required:
let plainTextValue = value => typeof value == 'Map' ? new RichText(value).plainText : value ;
plainTextValue(issue.customfield_10080 != null) && plainTextValue(issue.customfield_10080) != ''Incorrect condition script
Run code will not execute as the return result is a list of objects.
issue.comments.map(c => c.body)Issue must be in the current active sprint
As a project manager, you want to ensure that only issues planned in the current sprint are worked on. Allow work to be started only on issues that are in the current active sprint.
issue.sprint?.state == 'active'Issue must have at least one PDF attachment
issue.attachments.some(attachment => attachment.mimeType == 'application/pdf') Issue must have at least three PDF attachments
issue.attachments.filter(attachment => attachment.mimeType == 'application/pdf').length > 3Last field changed
Check whether a specified field has been changed within the issue lifetime.
issue.changelogs[0].items.some(i => i.field == 'Field Name')Linked issues
Use the Linked Issues Condition to control whether or not a user can transition an issue based on the status or resolution of linked issues.
// Check all linked issue are in certain status
issue.links.every(l => l.linkedIssue.status.name == 'Done')
// Check all linked issues of a certain link type are at certain status
issue.links
.filter(l => l.direction == 'inward')
.filter(l => l.type.inward == 'is blocked by')
.every(l => l.linkedIssue.status.name == 'Done')
// Check all linked issues have a resolution
issue.links.every(l => l.linkedIssue.resolution != null)
// Check all linked issues of a certain link type have a resolution
issue.links
.filter(l => l.type.inward == 'is blocked by')
.every(l => l.linkedIssue.resolution != null)Minimum length of all comments
As a support manager, you want to ensure that all comments have detailed descriptions. By setting a minimum character length, you can enforce meaningful comments on all issues before they can be created.
issue.comments.every(comment => comment.body.plainText.length > 10)Minimum length of issue description
As a support manager, you want to ensure that all reported bugs have detailed descriptions so you can replicate and solve them as easily as possible. By setting a minimum character length, you can enforce thorough descriptions of all issues before they can be created.
issue.description.plainText.length > 30Change length > 30 to specify the minimum number of required characters.
Multi-select or checkbox field equals a specific set of values
issue.customfield_10214 ?
issue.customfield_10214.map(option => option.value) == ['Yes', 'No'] :
falseMulti-select list or checkbox field must be populated with specific value
You want to enforce that issues have a specific value selected in a multi-select list or checkbox before progressing.
issue.customfield_10263 ?
issue.customfield_10263.some(option => option.value == "End Users") :
falseReplace customfield_10263 in the example with the ID of the multi-select list or checkbox field of your instance. To find the custom field ID, navigate to <JiraBaseURL>/secure/admin/ViewCustomFields.jspa and Edit the required field. The field ID is shown.
Multi-select or checkbox must be populated with one specific value
issue.customfield_10214 ?
issue.customfield_10214.some(option => option.value == "A") :
falseRegular expressions
The Regular Expression condition is only available on all strings, including text fields and option values.
Checks that the description contains the string `SRJ-` then any amount of digits, for example to match an issue tracker key:
issue.description.plainText.match("SRJ-\d+") != nullChecks if the regular expression exists in any part of the text field value.
issue.customfield_10206 ?
issue.customfield_10206.match("SRJ-\d+") != null :
falseRequire a comment on transition
issue.comments.some(comment => comment.id == null)Require all issues in an epic must be done
issue.isEpic && issue.stories.every(story => story.status.name == 'Done')Require at least one component
issue.components.length > 0Require at least one fix version
issue.fixVersions.length > 0Require at least two PDF attachments are added during the current transition
issue.attachments.filter(attachment => attachment.id == null && attachment.mimeType == 'application/pdf').length > 1Require attachments
You want a PDF of the contract agreement attached to an issue before work can begin, so developers know what was agreed with the client. This script ensures at least one PDF file is attached before the Start Progress transition is available for the issue.
issue.attachments.some(attachment => attachment.mimeType == 'application/pdf')If you want to require a specific minimum number of PDFs, use the following script:
issue.attachments.filter(attachment => attachment.mimeType == 'application/pdf').length > 2Edit length > 0 to the minimum number of PDFs required.
As a project manager, you want to ensure the required number of attachments have been added to an issue as it transitions, to align with business processes. Ensure a minimum number of attachments have been added as an issue transitions.
issue.attachments.filter(attachment => attachment.id == null).length == 3Change length ==3 to specify the minimum number of required attachments. The transition screen must be configured with the Attachments field, to allow users to submit the attachments during the transition.
Require one linked issue
You have a support portal and a separate support development instance. You want to ensure that all issues created on the support development instance are linked to their corresponding user-facing ticket on the support portal. Ensure all issues created on one Jira instance are linked with their corresponding issue on another instance.
issue.links.length > 0You can edit this script to make other fields required. For example, replace links with fixVersions or components.
Require specific users in a project can create issues of a specified type
In this example, only members of the Developers role can create Bug issue types, but all users can create other issue types.
issue.issueType.name == 'Bug' ?
user.getProjectRoles(project).map(p => p.name).includes("Developers") :
trueRequire sub-tasks
As a project manager, you want developers to add sub-tasks to issues so you can see the steps required to complete an issue. You want to prevent the transition of an issue if it has no sub-tasks. This script only shows the transition option if the issue has at least one sub-task.
issue.subtasks.length > 0Edit length > 0 to the minimum number of sub-tasks required.
Restrict transition permissions
As a team lead, you want to restrict the transition of issues to specific status for certain user groups or project roles. This condition only shows a certain transition option to users belonging to the groups or roles specified.
Restrict to project role
user.getProjectRoles(project).some(p => p.name == "userrole")Replace userrole with the project role you want to be able to transition the issue (for example, Developers). Roles apply to projects only, whereas user groups are global. See the Atlassian documentation for information on managing project roles.
Restrict to user groups
user.groups.includes('usergroup')Replace usergroup with the group of users you want to be able to transition the issue (for example, Administrators). See the Atlassian documentation for information on viewing, creating, or deleting groups.
Specify that one of two label fields must have a value
Note that you should replace 'customfield_12345' and 'customfield_67890' in the example below with IDs of the label fields inside your instance:
issue.customfield_12345 != null || customfield_67890 != nullSpecify the current user must be in a defined list of users
The example checks by user account ID, but you can also use user.displayName.
['accountIdHere', 'accountIdHere'].includes(user.accountId)Subtask type and status
This expression checks whether all subtasks of a certain type are at a specific status.
issue
.subtasks
.filter(s => s.issueType.name == 'Scope Change')
.every(d => d.status.name == 'Done')Sub-tasks must be done
You want to enforce that Done means all sub-tasks are completed by hiding the Done transition option of an issue when there are outstanding sub-tasks. This script only shows the transition option when all sub-tasks have the Done resolution.
issue.subtasks.every(subtask => subtask.status.name == 'Done')Edit subtask.status.name == 'Done' if you require a different sub-task resolution or status.
Sub-tasks must be in progress
As a project manager, you want to ensure all sub-tasks have been started before progress can start on the parent issue to keep issues aligned. Ensure all sub-tasks are In Progress before a parent issue can be transitioned to In Progress.
issue.subtasks.every(subtask => subtask.status.name == 'In Progress')Sub-Tasks must have assignee
You want to make sure all sub-tasks have been assigned before the parent issue can be transitioned to In Progress. This script only shows the In Progress transition option on a parent issue when all sub-tasks have assignees.
issue.subtasks.every(subtask => subtask.assignee != null)User(s) and user group(s)
Check the current user is one of a specified list.
['User A','User B','User C'].includes(user.displayName)Check the current user is in within a group of a specified list
['Group A','Group B', 'Group C'].some(g => user.groups.includes(g))User in field(s)
This expression will check whether the current user is selected within a custom user picker field.
For user picker single select:
issue.customfield_10213?.displayName == 'A User'
// or using accountId
issue.customfield_10213?.accountId == '5cf7c174eba28b4ea84a7cb5'For user picker multi select:
issue.customfield_10219 ?
issue.customfield_10219.some(user => user.displayName == 'A User') :
falseThis expression will check whether the current user group is selected within a custom group picker field, either by account ID or username.
For group picker single select:
issue.customfield_10077?.name == 'jira-admins'For group picker multi select:
issue.customfield_10078 ?
issue.customfield_10078.some(c => c.name == 'jira-admins') :
falseVerify issue type
Returns true for issues with issue type: Bug or Task.
["Bug", "Task"].includes(issue.issueType.name)