Synchronization of ADO fails due to the assignee

Hello,

When synchronizing ADO → Jira, the outgoing synchronization fails. I took a look at the JSON from Azure DevOps and noticed that the assignee is not set correctly for the items that fail.

Do you have any suggestions how to migrate those work items without re-assigning the assignee?

Here is an excerpt from the Azure DevOps JSON of the API.

Works:

“System.AssignedTo”: {

“displayName”: "Hans Musterfrau,

“url”: “”,

“_links”: {

“avatar”: {

“href”: “htt://dev.azure.com/abcde/_apis/GraphProfile/MemberAvatars/aad.MGfgdf5gf564”

},

“id”: “891-155-22”,

“uniqueName”: “Hans.Musterfrau@biontech.de”,

“imageUrl”: “https://dev.azure.com/12346/\_apis/GraphProfile/MemberAvatars/aad.bliblablud”,

“inactive”: true,

“descriptor”: “aad.ABCDEFG”

},

Does not work:

“System.AssignedTo”: {

“displayName”: “John Doe”,

“id”: null

},

The actual error:

com.exalate.api.exception.bug.BugException: Unexpected error occurred. Generate an exalate support.zip file and contact support. at com.exalate.error.services.BugExceptionCategoryService.generateBugException(BugExceptionCategoryService.scala:37) at com.exalate.replication.services.replication.EventSchedulerFromTrackerService$$anonfun$scheduleSyncWithPayloadFromTracker$6.applyOrElse(EventSchedulerFromTrackerService.scala:376) at com.exalate.replication.services.replication.EventSchedulerFromTrackerService$$anonfun$scheduleSyncWithPayloadFromTracker$6.applyOrElse(EventSchedulerFromTrackerService.scala:359) at scala.util.Failure.recover(Try.scala:233) at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:487) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:63) at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:100) at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18) at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:94) at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:100) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:49) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.util.NoSuchElementException: JsError.get at play.api.libs.json.JsError.get(JsResult.scala:53) at play.api.libs.json.JsError.get(JsResult.scala:52) at azurenode.services.node.client.JsonValue$$anon$1.reads(JsonValue.scala:44) at play.api.libs.json.JsValue.validate(JsValue.scala:18) at play.api.libs.json.JsValue.validate$(JsValue.scala:17) at play.api.libs.json.JsObject.validate(JsValue.scala:116) at play.api.libs.json.JsReadable.as(JsReadable.scala:23) at play.api.libs.json.JsReadable.as$(JsReadable.scala:23) at play.api.libs.json.JsObject.as(JsValue.scala:116) at azurenode.services.node.client.JsonValue$JsonToValue$.toWorkItem(JsonValue.scala:98) at azurenode.services.node.client.AzureClient.$anonfun$getWorkItemForProject$7(AzureClient.scala:597) at scala.Option.map(Option.scala:242) at azurenode.services.node.client.AzureClient.$anonfun$getWorkItemForProject$6(AzureClient.scala:595) at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:467) … 12 more

SearchDocumentationTool(query=“Azure DevOps assignee null synchronization error Jira”)
It looks like you’re running into a sync failure when the Azure DevOps (ADO) work item’s assignee field is either missing or incomplete, which causes Exalate to throw an error during synchronization to Jira. Based on the error and your JSON samples, the issue is likely due to the “System.AssignedTo” field being null or not containing the expected structure, which Exalate’s sync script or internal processing expects.

Here’s what you can do to handle this scenario and migrate those work items without needing to re-assign the assignee:

  • In your outgoing sync script on the ADO side, you can add a check to see if the assignee exists and is valid before attempting to map or send it. If it’s missing or null, you can skip setting the assignee field, or set it to a default value (like unassigned) on the Jira side.

For example, your sync script might look like this (in Script mode):

if (workItem.assignee && workItem.assignee.displayName) {
    issue.assignee = workItem.assignee.displayName
} else {
    // Optionally, set to null or a default user, or skip assignment
    issue.assignee = null
}

This way, items without a valid assignee won’t cause the sync to fail.

You can find more details and examples on handling user fields and null values in the Exalate documentation here:
https://docs.exalate.com/docs/handling-user-fields-in-azure-devops

If you want to ensure that unassigned work items are migrated as “Unassigned” in Jira, you can explicitly set the assignee to null or to a specific Jira user as needed.

Let me know if you need a more specific script example or further details!

That does not work. I think there is a bug in the ADO connector. It throws this error, when the user is deleted from Azure AD.

Any other ideas how I can fix this issue without changing the original work item in ADO.

Hi,

My understanding of the issue is that you are syncing workItems from ADO to Jira.
Some workItems are erroring out in Exalate on the ADO side, and this is related to the assignee field.
If this is correct, may I ask what line of script are you using on the outgoing to send the assignee info please? This should not normally happen as Exalate is simply sending the item out here. But then you also talk about deletion of the user from the AD. Is it that you already have synced items, but when you delete a user (who is assigned to some workItems), this error pops up in Exalate?

Thanks
Majid

No, it’s only about the one-time outgoing synchronization from ADO to Jira. This generally fails if the ADO user no longer exists or has been deleted (but is still correctly listed in the ticket assignee.

However, Exalate does not even start executing the ADO outgoing script, but apparently fails when parsing the JSON of the ADO API.

This is the current code for syncing:

replica.assignee = workItem.assignee

I’ve also tried this one, but it makes no difference:

if (workItem.assignee && workItem.assignee.displayName) {

replica.assignee = workItem.assignee.displayName

} else {

// Optionally, set to null or a default user, or skip assignment

replica.assignee = null

}

HI @mbiehler_bnt

The Issue is when Azure DevOps has deleted/inactive users assigned to work items, the API returns:
“System.AssignedTo”: {
“displayName”: “John Doe”,
“id”: null // ← null value
}

But Exalate expects id: String (non-nullable), but receives null, causing JsError during JSON parsing.

This is an Exalate Azure node bug - it doesn’t handle deleted/inactive users.

I will raise this issue to Dev team but i guess it will take time to come in future releases.

So i would suggest to change the assignee of the Work Items for syncing them on remote side. even you can set them to “Unassigned”.

Thanks,

Sonal