-
Bug
-
Resolution: Unresolved
-
Low
-
None
-
10.3.6, 10.3.7
-
None
-
10.03
-
1
-
Severity 3 - Minor
-
Issue Summary
The version picker component in JIRA issue creation/edit forms displays duplicate version options when users type a complete version name that exactly matches a single version returned by the REST API. Instead of showing only the matching version, the picker displays both the actual version (e.g., "Version 1") and a "New Version" option (e.g., "Version 1 (New Version)"), creating confusion for users who expect to see only the exact match.
This issue occurs inconsistently across different projects, with some customers able to reproduce it reliably while others cannot in their environments. The affected Project needs to have hundreds of versions in order to reproduce the issue.
Steps to Reproduce
- Navigate to an JIRA project with large number of versions (hundreds) as Jira Project Administrator.
- Click "Create Issue" or edit an existing issue.
- In the version picker field (Fix Version/s or Affects Version/s), start typing a version name.
- Type the complete, exact name of an existing version (e.g., "Version 1").
- Wait for the REST API call to complete and return results.
- Observe the dropdown options displayed.
Expected Results
When the REST API returns exactly one version that matches the typed text completely:
- Only one option should be displayed in the dropdown: the exact matching version.
- No "New Version" option should be shown since an exact match already exists.
- Users should be able to select the single matching version without confusion.
Actual Results
When the REST API returns exactly one version that matches the typed text completely:
- Two options are displayed in the dropdown:
- The actual matching version (e.g., "Version 1")
- A "New Version" option (e.g., "Version 1 (New Version)")
- This creates confusion as users see what appears to be duplicate options
- The issue occurs inconsistently - some projects are affected while others work correctly
- The validation logic in OnlyNewItemsSuggestHandler.validateMirroring() incorrectly returns true for showing the "New Version" option even when an exact match exists
Issue Root Cause
The root cause is a race condition between the "(New Version)" option creation logic and the REST API response processing in the version picker component.
Detailed Technical Root Cause:
- User types a version name (e.g., "Version 1")
- OnlyNewItemsSuggestHandler.validateMirroring() is called to determine if "(New Version)" should be shown
- At this moment, the model's getDisplayableUnSelectedDescriptors() contains stale data (XYZ number of versions from initial load)
- Simultaneously, an AJAX REST API call is made to fetch filtered versions
- validateMirroring() finds no exact match in the stale model data and returns true - allowing "(New Version)" to be created
- The REST API responds with exactly one matching version
- formatSuggestions() is called with both the REST response (containing the exact match) AND the "(New Version)" option
- Result: User sees both options in the dropdown
The issue occurs because the validateMirroring() method checks the model state before the AJAX response has been integrated into the model, while formatSuggestions() receives the fresh AJAX data after the "(New Version)" option has already been created.
This issue will affect only projects with a high enough number of versions for the rece condition to be met or Jira instances that are already suffering from poor performance.
Workaround
The workaround is optional due to the minor impact of the issue. The existing validation won't allow the user to create a duplicate version if they try. The workaround can be used until a permanent fix can be implemented in the core JIRA codebase through the OnlyNewItemsSuggestHandler.validateMirroring() method to properly handle the timing synchronization between REST API responses and model state updates.
The workaround script should be added to the JIRA announcement banner using <script> tags. The script will automatically apply the fix when users access any page containing version picker fields, including:
- Issue create pages
- Issue edit pages
- Quick create dialogs
- Any other forms with version picker components
The fix is designed to be safe and non-intrusive - it will gracefully handle any errors and fall back to the original behavior if needed. Users can verify the fix is working through browser console logs that will show when duplicate options are detected and removed.
<script> // Simple banner fix for duplicate "(New Version)" issue (function() { 'use strict'; // Prevent multiple applications if (window.VERSION_PICKER_BANNER_FIX_APPLIED) { return; } var fixApplied = false; function applyVersionPickerFix() { if (fixApplied || !window.AJS || !AJS.OnlyNewItemsSuggestHandler || !window._) { return; } console.log('Applying version picker fix...'); var originalFormatSuggestions = AJS.OnlyNewItemsSuggestHandler.prototype.formatSuggestions; AJS.OnlyNewItemsSuggestHandler.prototype.formatSuggestions = function(descriptors, query) { var result = originalFormatSuggestions.call(this, descriptors, query); // Only process if we have a query and results if (!query || query.length === 0 || !result || result.length === 0) { return result; } var lowerCaseQuery = query.toLowerCase(); var hasExactMatch = false; var hasNewVersionOption = false; var newVersionItem = null; // Check what we have in the suggestions _.each(result, function(groupDescriptor) { if (groupDescriptor && groupDescriptor.items && typeof groupDescriptor.items === 'function') { _.each(groupDescriptor.items(), function(item) { if (item && typeof item.label === 'function') { var label = item.label(); // Found exact match if (label && label.toLowerCase() === lowerCaseQuery && !item.properties.noExactMatch) { hasExactMatch = true; } // Found (New Version) option if (item.properties && item.properties.noExactMatch && label && label.toLowerCase() === lowerCaseQuery) { hasNewVersionOption = true; newVersionItem = item; } } }); } }); // Remove duplicate if both exist if (hasExactMatch && hasNewVersionOption) { console.log('Removing duplicate (New Version) option for:', query); _.each(result, function(groupDescriptor) { if (groupDescriptor && groupDescriptor.items && typeof groupDescriptor.items === 'function') { var originalItems = groupDescriptor.items(); var filteredItems = _.filter(originalItems, function(item) { return !(item.properties && item.properties.noExactMatch && item === newVersionItem); }); if (filteredItems.length < originalItems.length) { groupDescriptor.items(filteredItems); } } }); } return result; }; fixApplied = true; console.log('Fix applied successfully!'); } // Hook into JIRA's existing event system function waitForJiraAndApply() { if (window.AJS && AJS.$ && typeof AJS.$(document).ready === 'function') { AJS.$(document).ready(function() { applyVersionPickerFix(); }); } else if (window.jQuery) { jQuery(document).ready(function() { applyVersionPickerFix(); }); } else { // Fallback: try again in 100ms setTimeout(waitForJiraAndApply, 100); } } window.VERSION_PICKER_BANNER_FIX_APPLIED = true; waitForJiraAndApply(); })(); </script>