Incorrect usage of JIRA/lucene search API

Hi everybody!
In our Jira 8.3.2 instance we have a lot of calculated fields that gather values from various projects.
When accessing the individual issues that contain these fields, the results are shown without any errors in the atlassian-jira.log file.
However, when we run filters that should return multiple issues containing these calculated fields (sometimes 1400 issues each containing 4-5 calculated fields), I get the below error message in the log file:

2020-04-01 10:13:47,174 g2gcrm-69914:Cron Service ERROR anonymous     [c.o.scriptrunner.customfield.GroovyCustomField] Script field failed on issue: XXXX-2127, field: Custom Field21
java.lang.IllegalStateException: Incorrect usage of JIRA/lucene search API. You can only create/use: ManagedIndexSearcher inside a context (request or Jira-Thread-Local). Check: JiraThreadLocalUtils for details.
	at com.atlassian.jira.index.ManagedIndexSearcherFactory.createFrom(ManagedIndexSearcherFactory.java:15)
	at com.atlassian.jira.issue.index.ThreadLocalSearcherCache$Cache.retrieveEntitySearcher(ThreadLocalSearcherCache.java:116)
	at com.atlassian.jira.issue.index.ThreadLocalSearcherCache.getSearcher(ThreadLocalSearcherCache.java:39)
	at com.atlassian.jira.issue.index.DefaultIndexManager.getEntitySearcher(DefaultIndexManager.java:888)
	at com.atlassian.jira.issue.index.DefaultIndexManager.getIssueSearcher(DefaultIndexManager.java:865)
	at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:38)
	at com.sun.proxy.$Proxy12.getIssueSearcher(Unknown Source)
	at com.atlassian.jira.issue.search.SearchProviderFactoryImpl.getSearcher(SearchProviderFactoryImpl.java:17)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getIssueSearcher(LuceneSearchProvider.java:130)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.searchDocuments(LuceneSearchProvider.java:443)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.searchDocuments(LuceneSearchProvider.java:450)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.runSearch(LuceneSearchProvider.java:439)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getHits(LuceneSearchProvider.java:218)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:362)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:135)
	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:140)
	at com.atlassian.jira.bc.issue.search.DefaultSearchService.search(DefaultSearchService.java:118)
	at com.atlassian.jira.bc.issue.search.SearchService$search.call(Unknown Source)
	at Script22.run(Script22.groovy:83)

The errors don’t appear on one of our staging environments but are present on the live instance which I assume is because the live environment is much busier and there are a lot of queries in the Lucene index.
I did some research and on the JiraThreadLocalUtils class, but unfortunately there is not much documentation to rely on.
The bit of code that I assume generates this error looks like:

com.atlassian.jira.issue.search.SearchResults searchResults = null;
try {
    searchResults = searchService.search(user, query, pagerFilter);
} catch (SearchException e) {
    e.printStackTrace();
    return (Double) 0 ;
}

I saw one idea on a post about adding “ThreadLocalSearcherCache.startSearcherContext()” and “ThreadLocalSearcherCache.stopAndCloseSearcherContext()” in the loop, transforming to:

com.atlassian.jira.issue.search.SearchResults searchResults = null
    try {
        threadLocalSearcherCache.startSearcherContext()
        searchResults = searchService.search(user, query, pagerFilter)
    } catch (SearchException e) {
        e.printStackTrace()
        return (Double) 0
    }finally {
        threadLocalSearcherCache.stopAndCloseSearcherContext()
    }

Has anybody tried this? Would anybody know if my approach is correct before sending it to the live environment?

Thanks!
Gabriel

2 Likes

Hi Gabriel

Have you found an answer to your above question? i.e. is it safe to use in a live environment?

Hi Tasmeen,
Unfortunately I do not have an answer to this but I am using the first method in a live environment.
However, I am suspecting that this is generating memory leaks and filling the Java Heap Memory in a fast pace.
I am planning a Jira upgrade in the following weeks and I am revisiting this issue.
I’ll post my findings when I have some news.

Gabriel

Hi @TasneemBhyat,
Just wanted to update on this topic, as I resolved it with the help of Adaptavist product support.
The following bit of code has worked for me and it got rid of the errors that were appearing in the logs:

com.atlassian.jira.issue.search.SearchResults searchResults = null
try {
    ThreadLocalSearcherCache.startSearcherContext()
    searchResults = searchService.search(user, query, pagerFilter);
} catch (SearchException e) {
   e.printStackTrace();
   return (Double) total;
   }finally {
         ThreadLocalSearcherCache.stopAndCloseSearcherContext()
    }

You will have to include the import at the beginning:

import com.atlassian.jira.issue.index.ThreadLocalSearcherCache

Hope it helps!

Gabriel

1 Like

hi @GabrielUdvar1

Thank you very much for your replies. Much appreciated.

Using the above code, will it cause any performance impact. I would like to know this, especially in a JIRA Data Center environment which has 3 nodes.

PS… Also wanted to know if you are doing any manual reindex code before doing a search? If yes, could you please provide the code you use?

Thanking you
Tasneem