Edit: It turns out that I wasn't doing anything wrong. This is simply the nature of Forms and Jira. The value isn't written to the custom field until well after the ticket is created.
The solution is to put your Groovy code in a listener, instead of as part of a workflow transition.
I wrote a little explanation for anyone who needs it:
https://www.kennethmcclean.com/blog/the-forest-for-the-trees-custom-field-null-values-during-workflow-transitions/
****************************************
We have a groovy script that takes the value stored in a custom field on a ProForma form(the field is a single-user picker).
On create the script should move that value to a different field (and does a bunch of other things).
However it fails every time, as Jira insists that the initial value of the custom field is null.
If we set the script to run on any transition after create, it works fine. The script also works fine on existing tickets, using the Scriptrunner Console.
It’s as though the value of the custom field is not being set until well after the create transition has finished.
I simplified the script to just grabbing the value stored in the custom field, and logging still returns null.
Is there a way to ensure that the custom field value populates during the create transition?
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.Issue
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserManager
log.setLevel(Level.DEBUG)
UserManager usrMgr = ComponentAccessor.getUserManager()
CustomFieldManager cfMgr = ComponentAccessor.getCustomFieldManager()
CustomField lobCf = cfMgr.getCustomFieldObject("customfield_12345")
log.debug "customfield value is"+ issue.getCustomFieldValue(lobCf)