This page describes how to migrate a Connect Jira Issue Field module to Forge's custom field module.
Before you begin, make sure you review the basics of migrating Jira modules from Connect to Forge.
This migration involves two processes:
In your Forge manifest, remove each jiraIssueFields module from the connectModules section and rewrite each one
as a new jira:customField entry in the modules section.
For each new replacement jira:customField entry:
key value as the original jiraIssueFields module.migratedFromConnect field to true.You must set migratedFromConnect: true before you deploy. Otherwise, Forge cannot map the new jira:customField entry to the original Connect jiraIssueFields module, and your app will fail to migrate data from the corresponding Connect issue field.
In development environments, custom field names may include a suffix such as (Dev), that suffix does not appear in production. Migrating an existing Connect field to Forge does not change the field name.
Refer to the following sections for additional syntax conversion details of different field types.
1 2connectModules: jira:jiraIssueFields: - key: connect-read-only-string name: value: connect-read-only-string-field description: value: connect-read-only-string-field type: string
1 2modules: jira:customField: - key: connect-read-only-string name: connect-read-only-string-field description: connect-read-only-string-field type: string migratedFromConnect: true
For read-only Connect issue fields, the replacement Forge module must:
type in Forge manifest to the value in property.type in Connect.collection: list. See collection types for more details.connectFieldProperty refers to the entityProperty details used by the Connect issue field.key and path fields under connectFieldProperty are required to facilitate copying data from Connect to Forge during the migration task. Once the migration task is complete, these fields are unused.1 2connectModules: jira:jiraIssueFields: - key: connect-read-only-date name: value: connect-read-only-date-field description: value: connect-read-only-date-field type: read_only property: path: date key: statistics type: date
1 2app: id: ari:cloud:ecosystem::app/<<app_id>> connect: key: connect-fields-migration-test-app remote: connect authentication: jwt modules: jira:customField: - key: connect-read-only-date name: connect-read-only-date-field description: connect-read-only-date-field type: date migratedFromConnect: true readOnly: true connectFieldProperty: key: statistics path: date
For Connect single_select and multi_select issue fields, there is no direct equivalent in Forge. We recommend using a Forge object type custom field to achieve similar behaviour.
Forge object fields do not provide a built-in select UI. Your app is responsible for building a custom UI (using Forge UI Kit or Custom UI) that mimics the Connect select field experience, including rendering dropdowns, option lists, and multi-select chips. For more details, see Forge custom field rendering.
The existing Issue custom field options (apps) REST API continues to work for Forge custom fields migrated from Connect. Use the Forge custom field key (appId__envId__moduleKey) in place of the Connect issue field key in the request path:
1 2GET /rest/api/3/field/{appId__envId__moduleKey}/option
The request and response schema remains unchanged from Connect, including support for attributes, notSelectable, and project scope validation.
When an option's value or properties are changed via the Options API, Jira automatically updates the JQL index to reflect those changes, preserving the same behaviour as Connect.
When a field value is set or updated (via UI or API), Jira validates the selected option against the current scope, including project scope, project attributes, and notSelectable checks. This behaviour is identical to Connect.
Connect option extractions can be replicated in Forge using searchAlias on object schema properties. Each property you want to be searchable via JQL should have a searchAlias defined in the manifest schema.
5). In Forge, the payload must be a JSON object, at minimum {"id": 5}. To maintain backward compatibility, apps can define a parser expression that accepts a bare option ID and converts it to the required object format.= operator not supported on root field: Forge object fields do not support the = operator directly on the field. Instead, use = on a property exposed via searchAlias. For example, the Connect query customfield_10010 = "Apple" becomes customfield_10010.value = "Apple".Existing saved filters that use = on the root field will need to be updated to use the searchAlias syntax. Alternatively, customers can use the ~ operator to search the entire value stored in the field.
The Forge object stores the selected option as a JSON object containing the option id, display value, and any optionProperties:
1 2{ "id": 5, "value": "Apple", "optionProperties": { "type": "Fruit" } }
1 2connectModules: jira:jiraIssueFields: - key: connect-single_select-field name: value: connect-single_select-field description: value: Sample Connect single_select issue field. type: single_select extractions: - path: type type: string name: fruitType
1 2modules: jira:customField: - key: connect-single_select-field name: connect-single_select-field description: Stores a JSON Forge object entered by the user. # Schema defined for JQL search and backend validation. migratedFromConnect: true type: object connectFieldProperty: connectFieldType: SINGLE_SELECT view: formatter: expression: 'value != null ? JSON.stringify(value) : ""' export: true schema: type: object properties: id: type: number searchAlias: id value: type: string searchAlias: value optionProperties: type: object properties: type: type: string searchAlias: type additionalProperties: true additionalProperties: true required: - id - value - optionProperties
For a Connect single_select issue field, the replacement Forge jira:customField manifest must:
connectFieldType under connectFieldProperty to SINGLE_SELECT.formatter so that JQL results display similarly to a Connect single_select field.searchAlias on id so option update and replace operations apply across issues; use searchAlias on value (and on nested properties such as type) so JQL can match option values and extractions.required so invalid payloads are caught during validation.For public Jira APIs such as issue create or issue update, the payload can be minimal and Jira automatically hydrates the remaining data such as value and optionProperties:
1 2{ "id": 5 }
For private app APIs, the app must send the full object:
1 2{ "id": 5, "value": "Team 1", "optionProperties": {} }
Since multiple options can be selected, each property is stored as an array. For example, if options Apple and Banana are both selected:
1 2{ "id": [1, 2], "value": ["Apple", "Banana"], "optionProperties": { "type": ["fruit", "fruit"] } }
1 2connectModules: jira:jiraIssueFields: - key: connect-multi_select-field name: value: connect-multi_select-field description: value: Sample Connect multi_select issue field. type: multi_select extractions: - path: type type: string name: fruitType
1 2modules: jira:customField: - key: connect-multi_select-field name: connect-multi_select-field description: Stores a JSON Forge object entered by the user. # Schema defined for JQL search and backend validation. migratedFromConnect: true type: object connectFieldProperty: connectFieldType: MULTI_SELECT view: formatter: expression: 'value != null ? JSON.stringify(value) : ""' export: true schema: type: object properties: id: type: array items: type: number searchAlias: id value: type: array items: type: string searchAlias: value optionProperties: type: object properties: type: type: array items: type: string searchAlias: type additionalProperties: true additionalProperties: true required: - id - value - optionProperties
For a Connect multi_select issue field, the replacement Forge jira:customField manifest must:
connectFieldType under connectFieldProperty to MULTI_SELECT.id, value, and optionProperties in the schema. The schema of optionProperties should mirror the properties of the Connect select field option. Because this is a multi_select equivalent, each of these properties should be marked as an array.formatter so JQL results display similarly to Connect multi_select fields.searchAlias on id, value, and nested properties so the option APIs and JQL search behave in the same way as for Connect single_select fields.For public Jira APIs such as issue create or issue update, the payload can be minimal and Jira automatically hydrates the remaining data such as value and optionProperties:
1 2{ "id": [1, 2] }
For private app APIs, the app should send the complete object:
1 2{ "id": [1, 2], "value": ["Banana", "Apple"], "optionProperties": { "type": ["fruit", "fruit"] } }
When a new Forge app version replaces Connect jiraIssueFields entries with Forge customField, installing the app triggers a Jira background task. This task:
customfield_10054 referred to the Connect issueField schema, then customfield_10054 will refer to Forge's customField schema after switching.Migration duration will depend on the usage of the Connect field. To minimise disruption, the most recently updated Jira issues are migrated first.
If the site has never had the Connect version of that issue field installed, no migration task runs. The custom field is installed using the standard Forge custom field installation flow instead.
Your Forge app can use the following API endpoint to track the migration status of a specific customField:
1 2GET /rest/atlassian-connect/1/migration/{connectKey}/{jiraIssueFieldsKey}/task
The value of connectKey is the Connect app key, and jiraIssueFieldsKey is the key of the Jira Issue Field module.
For example, to track the sample Read-only field entry, use:
1 2GET /rest/atlassian-connect/1/migration/connect-fields-migration-test-app/connect-read-only-date/task
For more information, see the Task progress API documentation.
Once a module is migrated to Forge, it cannot be migrated back to Connect. Doing so is not supported and can result in undefined behaviour. If you need a gradual rollout, you can opt in to the staged migration program for Marketplace apps.
STRINGNUMBERREAD_ONLYSINGLE_SELECTMULTI_SELECTYou are now ready to verify the migration on a Jira instance that your team uses for testing. We recommend testing the migration in your development environment first, and only rolling it out to production (all customers) after successful verification. The checks below apply to every migrated field; additional steps apply only where noted for single_select and multi_select fields.
Install the Connect app on your test Jira instance (if it is not already installed). Ensure there are existing issues that use the migrated custom field with representative data, so you can compare behaviour before and after migration.
Adopt Forge for your Connect app following this guide.
Replace the Connect jira:jiraIssueFields module with the equivalent Forge jira:customField module in your app manifest. Set migratedFromConnect: true for every migrated field, and align the rest of the manifest with the field type you are migrating (see String and Number fields, Read-only fields, or Select fields as appropriate). Deploy and install the updated app on the Jira instance.
Verify that the migration task has completed. Use the Task progress API to confirm the task status is COMPLETE. Migration may take a few minutes to hours depending on the volume of data.
Verify that the custom field name is preserved. The migrated field should retain the same name as the original Connect field.
Verify that existing custom field data is accessible and works as expected for your field type:
customField definition expects.searchAlias paths on object fields).If you migrated single_select or multi_select fields, also confirm:
id, value, and optionProperties (where used) match what you expect when read from the API.searchAlias (for example customfield_XXXXX.value = "Apple") returns the expected issues.appId__envId__moduleKey).Rate this page: