Jira Cloud native Team field not updating — replica type UNHANDLED

Hi Exalate Support,

We use Exalate Classic in Script mode between two Jira Cloud instances.
We need to map a source Atlassian native Team to an existing destination Atlassian native Team. But unfortunately the destination’s Team field remains unchanged.

Expected mapping

“Team names and IDs below are anonymized.”

  • Source Team: ATenant-Team1 with ID: UUID1
  • Destination Team: BTenant-Team2 with ID: UUID2

Actual result

The destination Team remains BTenant-Team3, with ID UUID3.

What we have checked

  • The destination native Team field is customfield_10001, and the Team field appears in the replica with type UNHANDLED.
  • The incoming replica contains the correct source Team ID.
  • The Team value contains id, name, and title directly.
  • The incoming ID’s runtime type is com.google.gson.JsonPrimitive.
  • We updated the ID extraction to use getAsString(), but the destination Team still does not change.
  • Our incoming script attempts to set the Team field’s value to a map containing the mapped destination ID.
  • We have not yet independently confirmed whether execution reaches that assignment after ID conversion.

Could you please confirm:

  1. What is the supported way to set the native Jira Cloud Team field to an existing local team by ID?
  2. Is direct incoming-script assignment supported, or is a Jira REST API call required?
  3. What diagnostics should we collect to identify why the value remains unchanged?
  4. Does the UNHANDLED field type affect Exalate’s ability to write to the native Jira Cloud Team field? Does this field require a specific assignment format or special handling?

The anonymized incoming Team mapping script is included below. We can provide the actual replica excerpt and additional diagnostics on request.

Thank you!

The JSON below is a reconstructed example of the reported structure, not a verbatim replica export.

{
  "Team": {
    "id": "10001",
    "type": "UNHANDLED",
    "value": {
      "id": "UUID1",
      "name": "ATenant-Team1",
      "title": "ATenant-Team1"
    }
  }
}

The incoming groovy script

// Anonymized excerpt of the current Incoming script.
// UUID placeholders are for support review only, not for execution.

def teamMapping = [
    // Source Team       -> Destination Team
    "UUID1": "UUID2", // ATenant-Team1 -> BTenant-Team2
    "UUID4": "UUID5"  // ATenant-Team5 -> BTenant-Team6
]

def remoteTeamId = replica.customFields?."Team"?.value?.id?.with { value ->
    if (value instanceof com.google.gson.JsonPrimitive) {
        value.getAsString()
    } else if (value instanceof CharSequence) {
        value.toString()
    } else if (value instanceof com.fasterxml.jackson.databind.JsonNode) {
        value.asText()
    } else {
        null
    }
}

def localTeamId = issue.customFields?."Team"?.value?.id?.with { value ->
    if (value instanceof com.google.gson.JsonPrimitive) {
        value.getAsString()
    } else if (value instanceof CharSequence) {
        value.toString()
    } else if (value instanceof com.fasterxml.jackson.databind.JsonNode) {
        value.asText()
    } else {
        null
    }
}

// Preserve the existing Team guard exactly as currently configured.
if (remoteTeamId
    && remoteTeamId == "UUID4"
    && localTeamId != "UUID2") {
    // Leave the Team field unchanged.
} else {
    if (remoteTeamId && teamMapping.containsKey(remoteTeamId)) {
        issue.customFields."Team".value = [id: teamMapping[remoteTeamId]]
    }
}

You’ve provided a thorough breakdown of your scenario—thank you for the detailed context and script! Here’s a summary of what’s happening and guidance on your questions:

1. Supported way to set the native Jira Cloud Team field by ID

  • The Atlassian “Team” field in Jira Cloud is a special, native field (not a standard custom field) and is often marked as UNHANDLED in Exalate replicas. This means Exalate does not natively support direct mapping or assignment for this field in Script mode.
  • Direct assignment in the incoming sync script (e.g., issue.customFields."Team".value = [id: ...]) typically does not work for the native Team field, even if you provide the correct ID. This is due to the field’s special handling in Jira Cloud and Exalate’s current limitations.

2. Is direct assignment supported, or is a REST API call required?

  • For the native Team field, direct assignment in the script is not supported. You will need to use the Jira REST API to update this field on the destination issue.
  • This involves making an authenticated REST call from your incoming sync script to set the Team field using its custom field ID (e.g., customfield_10001) and the correct team ID.

3. Diagnostics to collect

  • Enable Exalate sync logs and check for any errors or warnings related to the Team field update.
  • Confirm whether your script block is being executed by adding logging statements (e.g., logger.info("Setting Team field to: " + teamMapping[remoteTeamId])).
  • Check the Exalate issue history and Jira issue history to see if any update attempts are logged.
  • Review the REST API response (if you implement it) for errors.

4. Does the UNHANDLED type affect Exalate’s ability to write to the field?

  • Yes, the UNHANDLED type means Exalate does not have built-in support for this field and cannot process it natively. Special handling (such as a REST API call) is required.
  • The assignment format for the Team field is not standard; it expects a specific structure and permissions, which is why direct assignment fails.

References and further reading:

Next steps:

  • Implement a REST API call in your incoming sync script to update the Team field. You’ll need to handle authentication (usually via an API token) and construct the correct payload.
  • Example REST call (pseudocode):
def teamId = teamMapping[remoteTeamId]
if (teamId) {
    def apiUrl = "/rest/api/3/issue/${issue.key}"
    def payload = [
        fields: [
            "customfield_10001": [id: teamId]
        ]
    ]
    httpClient.put(apiUrl, payload)
}
  • Make sure to replace "customfield_10001" with your actual Team field ID and handle authentication securely.

If you need a more detailed code example or run into issues with the REST API approach, let me know! For more details, check the documentation links above.

It worked, thank you!

I tested both approaches:

  • Direct assignment to issue.customFields."Team".value using the mapped Team ID as a string did not update the field.
  • The setTeam helper using httpClient.put successfully updated it, without supplying a separate API token.

For the REST request, the key was passing the Team ID directly as a string, rather than an object containing id. The object format was rejected as an invalid team identifier.

So, in our tested setup, the REST-based helper works, while direct field assignment does not.

import groovy.json.JsonOutput
def setTeam = { String issueKey, String teamId ->
  if (!issueKey?.trim() || !teamId?.trim()) {
    throw new IllegalArgumentException(
      "A Team frissítéséhez issueKey és teamId szükséges."
    )
  }
  def endpoint = "/rest/api/2/issue/${issueKey}"
  def updatePayload = [
    fields: [
      customfield_10001: teamId
    ]
  ]
  def jsonBody = groovy.json.JsonOutput.toJson(updatePayload)
  try {
    httpClient.put(endpoint, jsonBody)
  } catch (Exception e) {
    throw new Exception(
      "Team frissítési hiba: issue=${issueKey}, teamId=${teamId}: ${e.message}",
      e
    )
  }
}


.....

setTeam(issue.key, teamMapping[remoteTeamId])