Forge Jira issue panel extension providing incorrect localId value

Since February 3rd Forge issue panels are receiving incorrect value of localId inside of productContext. The value is equal to extensionId, while it should be in the format of {extensionId}-{panelInstanceId}-{timestamp}.

The app is affected if it uses localId to store panel data based on it. As we are dealing with data write under different key there will most likely be required data migration to recover from this scenario. Without action from app side it probably will be impossible to recover without loosing some data. If the app could be made ready for revert of incorrect localId behavior then we can carefully execute this change without loosing any data.

We initially released change to all production with exception to affected apps on affected tenants - the intention here is to prevent situation where app will suddenly lose connection to it’s data. If an app is affected and an update is required, the app owner received a notification from us in the form of an ADDON ticket on the ecosystem.atlassian.net site to coordinate the migration carefully. You can find the ADDON tickets assigned to your user by using this JQL.

If you haven’t been contacted and believe that any of your apps is affected, please reach out to us by creating an ECOHELP ticket (submit a request here: Report a bug ) with summary “Forge Issue Panels - localId”.

Here is potential solution on app side: when app receives the localId in a form of only {extensionId} it should keep working as is - load and store from {extensionId}|${issueKey} - we assume it’s current behavior. When app received the correct localId which is not equal to {extensionId} the app could ask for data from both keys and decide on result - pick the data to use and migrate data if it’s required.

Below there is a snippet with high-level potential fix. The logic needs to be kept “forever” or you can additionally perform background data migration before mitigation code is removed.

if (localId == extensionId) {
  // this is the current situation
  data = storage.get(`${localId}|${issueKey}`)
  // use the data
} else {
  // code path for the case where the localId != extensionId - which will happen once we apply the fix
  data = storage.get(`${localId}|${issueKey}`)
  dataToMigrate = storage.get(`${extensionId}|${issueKey}`) 
  if (data && !dataToMigrate) {
    // normal path - use data as usuall
  } else if (dataToMigrate && !data) {
    // data migration path - recovery from wrong localId
    storage.set(`${localId}|${issueKey}`, dataToMigrate)
    storage.delete(`${extensionId}|${issueKey}`)
    data = dataToMigrate
    // use data as usual from now - next execution will go to the normal path
  } else if (data && dataToMigrate) {
    // collision - resolve conflict (pick newer or show error and ask user to decide which data should be keept)
    // should only happen if panel used to have data and then was overridden with new data after localId changed
  }
}

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.