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

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Jira expressions - unique custom field in project

I am considering migration to cloud from server and looking if all custom scripts can be migrated.

We have one proj that has 5000 isses with custom fields named SerialNumber. We have one script that ensures unique value of SerialNumber field within project. It is added as validator in multiple places.

From what I undestand in cloud we have to work wth Jira Expressions. Can this validation be implemented using expressions?


6 answers

1 vote

Unfortunately, the Jira expressions language cannot run JQL searches, which I bet is what you're currently doing on Server.

The only workaround I can think of is to use a post-function to check the unicity of the serial number and send an email (or add a comment) if the serial number is not unique.

Thanks for reply, we use simple groovy script to execute jql and process results from that later:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.opensymphony.workflow.InvalidInputException

def issueManager = ComponentAccessor.getIssueManager()
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService.class)
def customFiledManager = ComponentAccessor.getCustomFieldManager();
def user = ComponentAccessor.getJiraAuthenticationContext().getUser()

//extract proj type and SN value
def serialNumberObject = customFiledManager.getCustomFieldObjectByName('Serial Number')
def projKey = issue.getProjectObject().getKey()
def serialNumber = issue.getCustomFieldValue(serialNumberObject)

//build and execute querry
def queryString = 'project = ' + projKey + ' AND "Serial Number" ~ "\\"' + serialNumber + '\\""'
def query = jqlQueryParser.parseQuery(queryString)
def results =, query, PagerFilter.getUnlimitedFilter())

// list issues with entered SerialNumber
def msg = ''
results.getResults().each {result ->
def resIssue = issueManager.getIssueObject(
msg += resIssue.key + ' '

// throw exception if sn exists
if(results.getTotal() != 0)
throw new InvalidInputException (serialNumberObject.getId(),"SN must be unique, entered arleady used in ${msg}")


Workarounds like email notifications can be done but this leads to dysfunctional project in our scenario. Worst case I could roll back change in post function?

I read that from validator project context variable is exposed. Can't we simply say something like project.issues.. ?

I must say that I am really confised how jira expressions are suposed to work. Do you have more detailed documentation with examples other than this one:


I believe that's the most extensive documentation there is (and it's the official documentation from Atlassian). JMWE includes online help for Jira expressions, but it's basically the same content.

What you'd want is this: But Atlassian has indicated they won't implement it.

Like John Funk likes this
0 votes
John Funk Community Leader Nov 02, 2020

Hi Pawhan - Welcome to the Atlassian Community!

You should also be able to use Jira Miscellaneous Workflow Extensions (JMWE) add-on to create a custom validator. 

@David Fischer _Appfire_ 

Please do explain.  I've been fighting the same battle as Pawhan and I can't find a way with this highly crippled "validator" tool.

Like John Funk likes this

Thanks for reply, i see that validators are very limited now.

What are the alternitives to enforce tkat kind of requirements? I am used to situation where on jira server scriptrunner allows me to do almost anything,

My only recommendation would be... patience. We are hoping that Atlassian will eventually open up Conditions and Validators beyond Jira expressions, once Forge becomes mainstream. But that will likely take another couple of years. 

Like pawhan likes this

Thanks for reply. Last question I hope, can this be achieved in post function with scriptrunner or other tool, espacially:

-run jql using rest api and process results

-delete issue

-sent custom email to person that created deleted issue



I can't speak for ScriptRunner, but this can certainly be achieved using JMWE for Jira Cloud. You can add a "Sequence of post-functions" post-function, and in that sequence add (in that order):

- an Email Issue(s) post-function

- a Delete Issue(s) post-function

And then add conditional execution on the Sequence to run the sequence only if the JQL search (run with the jqlSearch filter) returns an issue.

I worked out a way to do this.  It's not the prettiest but it will get the job done.

You need a new custom field, called "Validation Errors".  You will also need a new Workflow state.  Let's say that previously you had a workflow that looked like:

Working ------(Finish)-------> Done

where Working and Done are states and Finish is a transition.

Your new workflow should look like this:

Working ------(Test)------->Candidate------(Finish)-------> Done

Add additional Transitions from Candidate back to Working.  I call mine "Fix".

You should make your Candidate field read-only to anyone except scriptrunner by setting the State Property "" to "atlassian-addons-admin" (instead of just setting jira.issue.editable to false, which blocks scriptrunner).  You do this so that your test process is always correct, that you can't get to Done by simply deleting your working error and continuing workflow.

In your Finish transition, set a Condition such that your "Validation Errors" is empty, like

issue.customfield_10169 == null || issue.customfield_10169.length == 0

Now all that's left is for you to create a post-function that will populate your Validation Errors field with any validation issues that used to be your uniqueness Condition, back in Jira Server world.

Here's my such script, I have nothing proprietary here.  This will ensure that each subtask (segment template) will have a unique name within the context of the parent issue.  You could easily adapt this to be unique within some other dataset.

def errors = ""
def parent = issue.fields.parent.key
def siblings = "parent = ${parent} and key != ${issue.key}"
siblings = get("/rest/api/3/search?jql=" +, "UTF-8")).asObject(Object).body.issues
for (def s : siblings) {
if (s.fields.summary == issue.fields.summary) {
errors += "Summary \"${issue.fields.summary}\" is replicated by sibling segment template ${s.key}. Change one or the other of them before continuing.\n"

def fields = get("/rest/api/3/field").asObject(Object).body
def outputField = fields.find { == "Validation Errors"} "outputField ${outputField} into which shall be put \"${errors}\""
if (errors.length() > 0) {
.header('Content-Type', 'application/json')
.body ( [ fields: [ (
type: "doc",
version: 1,
content: [
type: "paragraph",
content: [
type: "text",
text: errors
] ] ] )
} else {
// for this to work, set Candidate property to atlassian-addons-admin
.header('Content-Type', 'application/json')
.body ( [ fields: [ (
type: "doc",
version: 1,
content: [ ]
] ] )

This way you can finally express a complex condition that includes a JQL expression, albeit indirectly, in one of these stupid, awful, virtually powerless Jira Expressions.

This was a hell of a lot of work to finagle a (hacky) solution.  I hope it helps somebody else!

Suggest an answer

Log in or Sign up to answer
Community showcase
Published in Jira

Atlympic Event: Jira

Hello Community!  Quick disclaimer: We are running a contest on Community (The Atlympics!) from July 23rd - August 8th of 2021. If you are interested in participating in this contest (prizes! ...

56 views 1 3
Read article

Community Events

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

Find an event

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

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you