Notes from the work

One email when a tutorial or migration write-up goes live. Nothing else, and an unsubscribe link in every email.

LeanZero

Two people in Romania doing Atlassian migrations, Forge apps and practical AI work for teams that would rather talk to the person doing the job. Most of what we learn ends up on this site.

Services

  • Atlassian Migrations
  • Atlassian FastShift
  • Atlassian Maintenance
  • Forge App Development
  • AI Development Consultation

Topics

  • Jira
  • Jira Service Management
  • Confluence
  • Bitbucket
  • Atlassian Forge
  • Cloud Migration
  • Local AI
  • AI Coding
  • Certifications
  • Atlassian Team
  • All topics

Company

  • Blog
  • Tutorials
  • Contact

Community

  • Join Discord
  • Support this site

© 2026 LeanZero. All rights reserved.

Privacy PolicyTerms of Service24/7 SupportTrust CenterSecurityDPALegal notice
  1. Home
  2. Blog
  3. Jcma Couldnt Export Custom Field Config Scheme
JCMA "We couldn't export Custom Field Config Scheme": three causes, three fixes
Cloud MigrationJira

JCMA "We couldn't export Custom Field Config Scheme": three causes, three fixes

Mihai Perdum
Mihai Perdum
Author
11 min readSeptember 30, 2026

Key takeaways

  • The same JCMA error has three documented causes: an orphaned project role in a user picker's User Filtering (the knowledge base), a context with a null name (MIG-2113), and Epic Status with no options on fresh Jira 8.15 or 8.16 installs (MIG-589).
  • Read the log line before you fix anything. The context name and the text after Reason tell the three causes apart.
  • The knowledge base's PostgreSQL query casts the role id to char, which is one character in Postgres, and its UPDATE matches a different id column from the one the instructions tell you to use.
  • Cloud exposes a single user picker's user filtering over REST as userFilter with enabled, groups and roleIds, so you can check what arrived after the migration.
  • Atlassian documents no Cloud-to-Cloud equivalent of this error, and says nothing about how Copy product data handles field contexts or user filtering.

JCMA stops with "We couldn't export Custom Field Config Scheme" and a java.lang.NullPointerException, and the same message has three unrelated causes. That is the trap. You search the error, you find Atlassian's knowledge base article for it, you run its SQL, it finds nothing wrong or it points you at a user picker you have never heard of, and the project still will not export.

The knowledge base article, JCMA export error: "We couldn't export Custom Field Config Scheme", was last updated on 26 September 2025 and documents one cause only. The second cause lives in a bug ticket, MIG-2113. The third lives in another, MIG-589. Both tickets are titled some version of "JCMA export throws java.lang.NullPointerException", and both are closed as fixed, but the data that triggers them can still sit in your database.

This piece is for the person holding a Data Center to Cloud migration that just failed on this line. There is a section at the end for Cloud to Cloud, which does not go through JCMA at all.

Why JCMA export throws java.lang.NullPointerException here

A custom field config scheme is what the Jira UI calls a custom field context: the combination of projects and issue types a field applies to, plus its options and default value. In the database it is the fieldconfigscheme table, and its name is the configname column. JCMA exports each context the projects in the migration use. If one of them has data the exporter does not expect, it throws a NullPointerException and that project's export stops.

The knowledge base puts it this way for its cause: JCMA "will identify that the information is corrupted and not proceed with the export of the affected projects." The affected projects, not the whole plan. That matches what people see: some projects go through, one does not.

Three causes of the JCMA export error on a custom field

Here are the three log lines, verbatim from Atlassian's own pages. Compare yours against them before you touch the database.

text
1Cause 1, knowledge base:
2<date> <time> ERROR <pkey> project-export We couldn't export Custom Field Config Scheme '<context-name>'. Reason: java.lang.NullPointerException: Parameter specified as non-null is null: method com.atlassian.jira.migration.export.framework.ExportService.exportOrThrow
3
4Cause 2, MIG-2113:
5project-export We couldn't export Custom Field Config Scheme 'null'. Reason: java.lang.NullPointerException: getName(...) must not be null. [JCMA 000]
6
7Cause 3, MIG-589:
8ERROR TP project-export We couldn't export Custom Field Config Scheme 'Default Configuration Scheme for Epic Status'. Reason: java.lang.NullPointerException.

The name in quotes and the text after Reason: are the tell. A real context name plus Parameter specified as non-null is null is cause 1. The literal word 'null' as the name plus getName(...) must not be null is cause 2. 'Default Configuration Scheme for Epic Status' is cause 3.

Orphaned project role in User Filtering

User picker fields can restrict who you can pick, by group or by project role. That setting is called User Filtering and it is stored per context, in userpickerfilter and userpickerfilterrole. The knowledge base says: "The following error message will appear when there is an orphaned or deleted project role ID linked to a User Filtering configuration associated with a custom field context." Delete a project role that a filter still points at and you have it.

The knowledge base gives a diagnostic query for PostgreSQL, MySQL, Oracle and SQL Server. This is the PostgreSQL one, verbatim:

sql
1SELECT cf.id                                                      AS customfieldid
2     , cf.cfname                                                  AS customfieldname
3     , fcs.id                                                     AS customfieldcontextid
4     , fcs.configname                                             AS customfieldcontextname
5     , upf.id                                                     AS userpickerfilterid
6     , upfr.projectroleid                                         AS userpickerfilterprojectroleid
7     , COALESCE(CAST(pr.id AS char), 'Project role ID not found') AS projectroleid
8     , COALESCE(pr.name, 'Project role name not found')           AS projectrolename
9  FROM userpickerfilter upf 
10  JOIN fieldconfigscheme          fcs ON                fcs.id = upf.customfieldconfig
11  JOIN customfield                 cf ON                 cf.id = upf.customfield
12  LEFT JOIN userpickerfilterrole upfr ON upfr.userpickerfilter = upf.id
13  LEFT JOIN projectrole            pr ON                 pr.id = upfr.projectroleid;

A row reading "Project role ID not found" is your orphan. The fix it gives is to pick a real role from the projectrole table and run:

sql
1UPDATE userpickerfilterrole SET projectroleid = <project-role-ID> where id = <affected-picker-filter-ID>;

followed by "create a new migration to migrate the project again". A new migration, not a retry.

Null configname in fieldconfigscheme

MIG-2113 is the second cause. Its steps to reproduce are two lines: "Have a null config name in the fieldconfigscheme table" and "Attempt a project by project migration via JCMA to Cloud". It lists Affects Version "JCMA - 1.12.8", it is Closed as Fixed, and the last comment, from 3 March 2026, says "Released on JCMA 1.12.53". The ticket's expected behaviour was to "Prompt users to update config schemes". It does not say what 1.12.53 actually does with a null name now, so if you are on an older JCMA, or you want to be sure, fix the data.

The workaround, verbatim, starts with "Before making any database updates perform a database backup in case a restore is required", then:

sql
1UPDATE fieldconfigscheme SET configname = '<Configuration Scheme Name>' WHERE id = <config scheme ID>;

Atlassian gives no query to find the row. This one is mine, not theirs:

sql
1SELECT id, fieldid, configname FROM fieldconfigscheme WHERE configname IS NULL;

Epic Status with no options on Jira 8.15 and 8.16

MIG-589 is the oldest of the three, created in May 2021 and closed as fixed that October. Its description: "For Jira versions 8.15 and 8.16 when running a migration with JCMA, the migration fails". The reason given is that "On those versions of Jira, no options for the Epic Status is created - therefore we don't have a default value for that field". The stack trace stops in CustomFieldConfigSchemeExporter.getDefaultValue, which fits.

Two conditions narrow it a lot. It "doesn't appear if you previously had an instance with 8.14 or earlier and upgraded to 8.15", so it is fresh 8.15 and 8.16 installs. And migrations "are successful when using Jira versions 8.14 or 8.17-EAP02". The only version statement on the fix is a comment: "Should have been in JCMA 1.5.8".

There is no SQL here. Epic Status is a locked Jira Software field, and "As the field is created in Jira Software there's no way to set it". The workaround is done in the UI, backup first: unlock the field, open Epic Status, remove the duplicated default configuration scheme so the project uses the global context, set the default value to "To Do", lock the field again, retry. One user on the ticket found two Epic Status fields in their list, one marked deprecated, and deleting the deprecated one fixed it. Another noted the field "is not even configured for the project we are trying to migrate, but still it's breaking the migration". So do not rule this cause out just because Epic Status is not configured for your project; one user on the ticket hit it that way.

Three problems in the knowledge base's own SQL

I ran the knowledge base's PostgreSQL query and fix on a throwaway PostgreSQL 16.15 database with a stub of these tables: only the columns the queries name, seeded with one good role, one deleted role, a filter pointing at both, a context with a null name, and an Epic Status context with no options. We have no Data Center instance, so this is not a real Jira schema, and the column names are taken from Atlassian's own query. Three things came out of it.

First, CAST(pr.id AS char). In PostgreSQL char with no length is one character. The query still flags the orphan correctly, because that is driven by COALESCE, but the role id it does find is cut short:

text
1 userpickerfilterprojectroleid |       projectroleid       |       projectrolename
2                         10100 | 1                         | Developers
3                         10101 | Project role ID not found | Project role name not found

Role 10100 shows as 1. Use CAST(pr.id AS varchar) if you want to read it.

Second, the fix points at the wrong id. The knowledge base says to take the id "from the userpickerfilterid column" of the query. That column is userpickerfilter.id. The UPDATE's WHERE id = is on userpickerfilterrole, a different table, and the query never returns that table's id. On my stub, running the UPDATE with the userpickerfilterid value, inside a transaction I rolled back, did this:

text
1UPDATE 0

It changed nothing because no role row had that id. On a real database the two id sequences can overlap, and then the same statement rewrites some other filter's role instead. The query to run first is this one, mine, which returns the id the UPDATE actually needs:

sql
1SELECT upf.id AS userpickerfilterid, upfr.id AS userpickerfilterrole_id, upfr.projectroleid,
2       COALESCE(CAST(pr.id AS varchar),'Project role ID not found')
3  FROM userpickerfilter upf
4  LEFT JOIN userpickerfilterrole upfr ON upfr.userpickerfilter = upf.id
5  LEFT JOIN projectrole pr ON pr.id = upfr.projectroleid;
text
1 userpickerfilterid | userpickerfilterrole_id | projectroleid |       projectroleid
2                  1 |                      11 |         10100 | 10100
3                  1 |                      12 |         10101 | Project role ID not found

With WHERE id = 12 the UPDATE hit exactly one row, the orphan, and left row 11 alone.

Third, a small one: the instruction tells you to replace an <affected-project-role-ID> placeholder that does not appear in the UPDATE, which has <project-role-ID> and <affected-picker-filter-ID>. And unlike both tickets, the knowledge base's fix carries no backup warning. Take the backup anyway.

For the other two causes the stub did what the tickets describe: my null-name query found the context, MIG-2113's UPDATE named it, and a count of Epic Status options per context returned zero for the seeded one. That last query joins options to contexts through a column I modelled myself, so treat it as a sketch until you have checked it against your own schema.

We couldn't import Custom Field Config Scheme: the Cloud side

The export message has an import sibling. A public Community thread, Can't proceed with server to cloud migration, shows it from June 2021:

text
1ERROR PTL project-import We couldn't import Custom Field Config Scheme 'n'. Reason: NullPointerException: No message. This caused 1 other items to fail.
2ERROR PTL project-import We couldn't import Custom Field Default Value 'NDT configuration scheme'. Reason: IllegalArgumentException: Expect one config for custom field config scheme 18405.
3ERROR PTL project-import We couldn't import Project PTL. Reason: IllegalArgumentException: Workflow scheme [14690] does not exist. This caused 4722 other items to fail.

The poster said of 'NDT configuration scheme' that "there is no scheme with that name", and the only reply, from Jack Brickey, asks whether it was ever solved. That is still a Data Center to Cloud run, failing on the Cloud side of it, not a Cloud-to-Cloud error.

After a migration that does go through, you can check what landed. On our own Cloud test site today, GET /rest/api/3/field/{fieldId}/context lists a field's contexts, and for a single user picker GET /rest/api/3/field/{fieldId}/context/defaultValue returns the user filtering too:

json
1{"type":"single.user.select","contextId":"12255","userFilter":{"enabled":false,"groups":[],"roleIds":[]}}

That userFilter object is the Cloud counterpart of the two tables above. A multi user picker on the same site returned only type and contextId, no userFilter key, and nothing I read explains why. I have not run a JCMA migration for this piece, so I cannot tell you whether a Data Center role id arrives in roleIds. Epic Status on the same site has one context, named "Default Configuration Scheme for Epic Status", the same name as in MIG-589, with three options: To Do, In Progress and Done.

This is the same check-on-the-destination habit as in the issue security level version of this error, which is the same class of failure: a JCMA NullPointerException over a reference to something that was deleted.

Custom field contexts in Cloud to Cloud migration

Cloud to Cloud has no JCMA, so you will not see this message, and there is no database to run SQL against. Atlassian's page What data is copied lists "✅ Field configuration scheme", "✅ Project roles", "Epic status" among the epic fields, and user pickers, single and multiple, among the custom field types it copies. It says nothing about field contexts or user filtering. I have not run a cross-site copy for this piece, so I cannot tell you how either behaves. What you can do is run the same two REST calls against the source and the destination and compare them field by field, using the destination's own field ids.

Before you rerun the server to cloud migration

Match the log line to one of the three causes first. For cause 1 get the userpickerfilterrole id from the corrected query, not the one the knowledge base names. For cause 2 find the null name and give it one. For cause 3 fix Epic Status in the UI. Then back up, fix, re-run the finding query until it returns nothing, and start a new migration for the project.

What this does not cover

The database half was run on a stub PostgreSQL schema, not a live Jira, and the MySQL, Oracle and SQL Server variants were not run. Atlassian publishes no finding query for causes 2 and 3; the ones here are mine. The Cloud half was read live, with no JCMA run behind it, and the Cloud-to-Cloud half rests on the documentation plus the REST check.

Custom field contexts are not the only thing a JCMA run can lose without a loud error. Jira 32,767 characters limit: find what JCMA lost covers truncated text, and Jira JQL counts a missing custom field as zero covers why a post-migration field audit can read 0 when the field is simply not there.

ShareXLinkedIn
PreviousAtlassian Data Security Policy: What It Blocks, What Needs Guard, and MigrationsNextRuns on Atlassian apps with AI: Sentinel Vault reviews Confluence with no API key

Tags

#jira#jcma#cloud-migration#cloud-to-cloud#custom-fields#data-center

Comments

0

Add a comment

Confirm your address using the email we send. You can unsubscribe at any time. Your email stays private and this does not sign you up for the newsletter.

Enjoyed?

Join our Discord community to discuss this article and get help with your own migration projects.

Discuss in Discord

On this page

  • Why JCMA export throws java.lang.NullPointerException here
  • Three causes of the JCMA export error on a custom field
  • Orphaned project role in User Filtering
  • Null configname in fieldconfigscheme
  • Epic Status with no options on Jira 8.15 and 8.16
  • Three problems in the knowledge base's own SQL
  • We couldn't import Custom Field Config Scheme: the Cloud side
  • Custom field contexts in Cloud to Cloud migration
  • Before you rerun the server to cloud migration
  • What this does not cover

Join the Community

Join the community to ask questions, share your work, and connect with other professionals.

Join Discord

Found My Advice Helpful?

If I helped you solve something for free, coffee money is always appreciated (but never expected).

Buy Me a Coffee

Related reading

Jira automation usage billing from 3 December 2026: step counts we measured on real rules

From 3 December 2026 Jira automation usage is billed per step. We built 11 everyday rules on our test site, ran them and read what each run cost. A scheduled rule that found nothing cost 1 step, and a branch over 5 sub-tasks cost 7. Below: how to read the same numbers on your site, and what to audit first.

10/15/2026

Is 25 Rovo credits per user enough? Cost and usage per action, measured

Rovo credits per user are 25, 70 or 150 a month on Jira and Confluence. We ran Rovo Chat on our own test org and read the meter after each message: Quick answers cost exactly 10, Think deeper cost 65 and 86. Then we worked out what that means for 50, 200 and 500 seats once billing starts on 3 December.

10/15/2026

Claude Code Hits a Jira Workflow Validator: CogniRunner Blocks the Change Request

I gave Claude Code a service-desk agent's API token and asked it to move a change request to Ready for CAB. Two plain-English CogniRunner validators sent back HTTP 400 with both reasons. Claude fixed the backout plan, left the failed rehearsal report alone and handed it back. I ran it three times and got the same outcome.

10/15/2026