Exalate overwriting Resolved status

I’m running into an issue with Exalate: when I change a ticket status to Resolved, Exalate sometimes automatically changes it back to Waiting for support. I then have to manually set it back to Resolved, which is annoying.

Does anyone know why this happens and how to prevent Exalate from overwriting my status changes?
I assume it maybe something within the scripts syntax?

What you’re experiencing is a common scenario when synchronizing issue statuses between two systems using Exalate. The status being overwritten (e.g., from “Resolved” back to “Waiting for support”) is usually due to how the sync scripts are configured on either side of your connection.

Here’s why this happens and how you can address it:

Why does this happen?

  • Exalate syncs issue fields (including status) based on the sync rules/scripts you have set up.
  • If the remote side changes the status and syncs back, your local status can be overwritten—even if you just updated it.
  • This is especially common if both sides are allowed to update the status, or if the sync scripts don’t account for recent local changes.

How to prevent status overwrites:

  • You can add logic to your Incoming Sync script to avoid overwriting the status if it was just changed locally, or to only update the status under certain conditions.
  • For example, you can compare the previous status with the incoming status and only update if they match, preventing a “ping-pong” effect.

Here’s a snippet you can use in your Incoming Sync script to help avoid these conflicts:

if (!firstSync && previous?.status.name == replica?.status.name) {
    // Only update the status if it hasn't changed locally since the last sync
    issue.status = replica.status
}

Or, if you’re using mapped transitions, you can control exactly when transitions happen:

if (issue.status.name == "In Progress" && replica.status.name == "Resolved") {
   workflowHelper.transition(issue, "Resolve")
}

Documentation references:

Review your sync rules and consider adding logic like the above to prevent unwanted status overwrites. This should help keep your “Resolved” status from being reset by Exalate.

Hi @Henryiulio

Just checking if the answer provided by the Aida help you.

If you need further clarification or assistance, please let me know.

Sincerely,
Kevin

I appreciate the follow-up, @Kevin ; Here’s the script I’ve put together—any thoughts on what might be missing or could be improved?

if (firstSync) {
    issue.projectKey  = "TECH"
    // Set the same issue type as the source issue. If not found, set a default.
    issue.typeName    = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task"
}
issue.summary      = replica.summary
issue.description  = replica.description
issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
issue.labels       = replica.labels

// --- Status Synchronization ---
def statusMap = [
        "pending"   : "Pending",
        "solved"    : "Resolved",
        "open"      : "Waiting for support",
]
def remoteStatusName = replica.status.name
def mappedStatus = statusMap[remoteStatusName] ?: "In progress"

// Only update status on first sync or if it hasn’t changed locally
if (firstSync || issue.status?.name == mappedStatus || issue.status == null) {
    issue.setStatus(mappedStatus)
} else {
    logger.info("Skipped status update to avoid overwriting local status. Local=${issue.status?.name}, Incoming=${mappedStatus}")
}

/*
    Custom Fields (CF)
    issue.customFields."CF Name".value = replica.customFields."CF Name".value
*/

/*
    User Synchronization (Assignee/Reporter)
    def defaultUser = nodeHelper.getUserByEmail("default@exalate.com")
    issue.reporter  = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
    issue.assignee  = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser
*/

/*
    Comment Synchronization (Impersonate author)
    issue.comments = commentHelper.mergeComments(issue, replica) {
        it.executor = nodeHelper.getUserByEmail(it.author?.email)
    }
*/

// Exalate API Reference Documentation: https://docs.exalate.com/docs/exalate-api-reference-documentation

Hi @Henryiulio

when you say that your changing the status to resolved, is on this side of the connection? Or that gets sync and then when update happens y changes back to in Waiting for support?

Would be possible to provide with the incoming and outgoing from both side to see what could be causing the unexpected behavior?

Best,
Kevin

Hi Kevin,

On my side, my team and I manually set the status to Resolved while being sync’d with Exalate. When we do, we receive an Exalate notice reflecting the status change. I’ve also added the following adjustments to my incoming sync script for handling statuses:

if (firstSync) {
    issue.projectKey  = "TECH"
    issue.typeName    = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Task"
}
issue.summary      = replica.summary
issue.description  = replica.description
issue.comments     = commentHelper.mergeComments(issue, replica)
issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
issue.labels       = replica.labels

def statusMap = [
    "pending" : "Pending",
    "solved"  : "Resolved",
    "open"    : "Waiting for support",
]
def remoteStatusName = [replica.status.name](http://replica.status.name)
def mappedStatus = statusMap[remoteStatusName] ?: "In progress"

// Only update status if it's the first sync or hasn't changed locally
if (firstSync || previous?.status?.name == replica?.status?.name) {
    issue.setStatus(mappedStatus)
}

Best,
Henry

Following up on any input on the recent comment?

Hi @Henryiulio

Apologies on the delay.

I can see a couple of things on that could be causing this undesired status change.

I would suggest trying with the following snippet and let me know if you still encounter issues

def statusMap = [
    "pending" : "Pending",
    "solved"  : "Resolved",
    "open"    : "Waiting for support",
]

def remoteStatusName = replica.status.name
def mappedStatus = statusMap[remoteStatusName] ?: "In progress"
    issue.setStatus(statusMap[remoteStatusName])

The main issue with your previous script was that previous?.status?.name == replica?.status?.name that condition is true when the status has not change on the remote side so if there is an update coming from Zendesk after you marked the case as resolved then Exalate is setting the default status.

Test the provided script and let me know who it goes.

Best,
Kevin