Unable to update a Custom Field that my own Forge app created

Hey, @KishoreMandyam,

That API works only for custom fields and custom field types defined in the Forge app manifest. It seems that in your app you created a field of a built-in type com.atlassian.jira.plugin.system.customfieldtypes:textfield. It is a regular custom field that can only be updated by regular means (with the edit issue API).

Thanks, @kkercz, I’ll look at this in more detail.

I used the Update only because, if I use the Custom Field in my Add API call, that fails with “Field ‘customfield_10037’ cannot be set. It is not on the appropriate screen, or unknown.” Why would that be? Is there no way I can use a Custom Field in the Add API?

Related: Why am I not able to see the Custom Field in any view, even though I have associated all my Screens with it?

BTW, just so I don’t bother people here with these very basic issues: Is there like a Guidebook or something that tells me what to do in the most common use-cases? Like creating my own custom-field and so on? Where should I have gone in the doc to know that I should first define my field in the manifest and then update it, instead of just using an API directly?

Pardon me for all the questions. Thank you for all your help!

Why am I not able to see the Custom Field in any view, even though I have associated all my Screens with it?

That’s unexpected. Usually adding fields to screens in your project should be enough. You could try to use the find your field functionality to find out what’s going on.

I’m afraid there is no comprehensive guide on how to extend Jira with custom fields. Definitely something we could improve!

@kkercz Coming back to this issue:
There IS no “Find your field” menu option in my instance of Jira, from any of the the overflow menus.

I have now moved to using a manifest-defined Custom Field, as below (instead of code-defined, as in my earlier post):

modules:

jira:customField:
- key: my_id
name: My ID
description: My external ID
type: string
readOnly: true

Now, the error I get is this:

Field ‘customfield_10038’ cannot be set. It is not on the appropriate screen, or unknown.

I have checked the following items:

  1. The custom field IS available in the response to this API: /rest/api/3/field
  2. It is not available in this one: /rest/api/latest/issue/{issue-id}
  3. There IS a context available: /rest/api/3/field/{field-id}/context
  4. It is not available among the availableFields here: /rest/api/2/screens/{screen-id}/availableFields
  5. It is not available in the field-configuration here, for the Default Field Configuration ID (10000): /rest/api/3/fieldconfiguration/{fld-config-id}/fields
  6. It has 3 screens here: /rest/api/3/field/{field-id}/screens
  7. It IS available in the app here: /secure/admin/ViewIssueFields.jspa?searchFilter={my-filter}&atl_token={some-token}

So, my questions:

  • Why am I able to see the field in the Default Field Configuration in the app but unable to see it in the API for the same configuration ID?
  • Why is the update failing now?
  • What can I do to fix this?

Thanks for your help!

The error message suggests it’s an issue with screens configuration. Are you certain that your field is added to screens that are associated with the issue you are trying update?

Why am I able to see the field in the Default Field Configuration in the app but unable to see it in the API for the same configuration ID?

Possibly because the API retrieves a default configuration, and the app shows a different one? Or maybe because the API doesn’t show fields without any custom settings, and the app shows all of them; have you tried making any changes to the field in the configuration (e.g. make the field required), and then seeing if the field is returned in the API?

Yes, the field IS in the Default Screen (in the Jira UI, here: /secure/admin/ConfigureFieldScreen.jspa?id=1).

The API and the app should both show the “default” configuration, right? But the API to get the list of available fields, /rest/api/2/screens/1/availableFields (where the 1 is the ID of the Default Screen - same as in the above UI URI) does not include the field.

BTW, the /rest/api/3/field/customfield_10038/screens API DOES show the Default Screen (as also two other screens that the field is on).

One other thing: I am using all these APIs in the same browser session as the one logged into Jira. So there can’t be user-ID issues.

Help!

I’m getting somewhere but nowhere near where I need to be. I now add the field to the default screen using the Forge API, right after the package installs. So now, I see the field in the /rest/api/2/screens/1/availableFields response. But the Field ‘customfield_10038’ cannot be set. It is not on the appropriate screen, or unknown. error refuses to go away. So even though I see the field on the Default Screen, per the API, the add-issue fails with the same error.

Does this custom-field mechanism actually work at all? For anyone else?

@kkercz I have now changed the code to add the issue first and then update it. The add works fine, the update fails with OAuth 2.0 is not enabled for method: PUT /rest/api/2/issue10045. Here’s my code:

//  insert the issue
var body_data = <some structure that works>;
var response = await api.asApp().requestJira(route`/rest/api/3/issue`, {
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    body: body_data
});  
var t1 = await response.json();
//  this works, issue is created OK

//  update the just-created issue with the value
var custom_field_identifier = stored_info.custom_field_info.schema.custom;
var bodyData = '{ "fields": { "' + custom_field_identifier + '": "' + api_body.column_value + '" } }';
var r1d1 = await api.asApp().requestJira(route`/rest/api/2/issue${t1.id}`, {
    method: 'PUT',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    },
    body: bodyData
});
var t2 = await r1d1.json();

The stored-info structure is just something I save when the app is installed, to use later.

And here’s the manifest, for the custom field:

jira:customField:
- key: my_external_id
name: My External ID
description: The external ID for this Issue
type: string

I’ve tried this with two different formats of the field key, one you’ve suggested here and the one shown here. Both give me the same error - the OAUTH 2.0 thing.

What am I doing wrong? Please help!

Hey, @KishoreMandyam,

Maybe try adding your field to a screen tab, not necessarily to a screen. And not just to the default screen, but to all screens, just to be sure? So use this API: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-screen-tab-fields/#api-rest-api-2-screens-screenid-tabs-tabid-fields-post.

Apart from that, have you tested configuring the field through the Jira UI? I just tried and all worked fine for me, i.e. I was able to create an issue via the REST API after I had installed my Forge field and added it to all screens manually.

When it comes to the issue update request you are making, the URL should be /rest/api/2/issue/10045 (with the slash between issue and 10045).

Hope this helps, let me know how it goes.

@kkercz thank you for those suggestions. I have now fixed the slash code-bug and added the field to the first tab on each of the 3 default screens (ids 1 through 3 - Default, Resolve Issue and Workflow) that the app has. I checked that the field is available on the screens in question, using the API /rest/api/3/screens/-scr-id-/tabs/-tab-id-/fields. The field is NOT available in the Previously-created Fields area of the project’s issue-types.

Now, the await api.asApp().requestJira(route/rest/api/2/issue/${issue.id} call gives me this error:

Field ‘ari:cloud:ecosystem::extension/–cloud-id–/–environment-id–/static/–field-key–’ cannot be set. It is not on the appropriate screen, or unknown.

I changed the code to use the alternate API (here), as below:

var bodyData = { "updates": [ { "issueIds": [ ${issue.id} ], "value": "${column_value}", "customField": "${custom_field_identifier}" } ] };

var  r1d1 = await api.asApp().requestJira(route`/rest/api/2/app/field/value`, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: bodyData
});  

This gives me a different error:

Custom field with id ‘ari:cloud:ecosystem::extension/–cloud-id–/–environment-id–/static/–field-key–’ doesn’t exist.

I guess they both mean the same thing, whatever that means. I am using the format of custom-field ID shown here.

What else should I be doing?

You need to provide the field ID in the form of customfield_xxx, as described in the documentation of the REST API. ari:cloud:ecosystem::extension/–cloud-id–/–environment-id–/static/–field-key– is not the ID of the field, but instead the ID/key of the field type.

The packet being submitted is this:

{ “update”: { “customfield_10051”: [ { “set”: “50028SjQAAV” } ] } }

The code is this (asApp):

const r1d1 = await api.asApp().requestJira(route/rest/api/2/issue/10091, {
method: ‘PUT’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: bodyData
});

The response is this:

{“headers”:{},“ok”:false,“status”:400,“statusText”:“Bad Request”}

If I use this code (asUser):

const r1d1 = await api.asUser().requestJira(route/rest/api/2/issue/10091, {
method: ‘PUT’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: bodyData
});

I get this failure-response:

{
message: ‘Authentication required’,
name: ‘NEEDS_AUTHENTICATION_ERR’,
status: 401,
serviceKey: ‘atlassian-token-service-key’
}

I have also tried the following with relevant packets, leading to more inventive failures:

await api.asApp().requestJira(route/rest/api/2/app/field/value,
await api.asUser().requestJira(route/rest/api/3/app/field/customfield_10051/value
await api.asApp().requestJira(route/rest/api/3/app/field/customfield_10051/value
await api.asApp().requestJira(route/rest/api/2/app/field/value

None of them have worked. Please help! :frowning:

BTW, I now create the field in the code, not via the manifest. So it shows up everywhere, including on the relevant screens and in the Automation pick-list (unlike when I set up the field via the manifest). I use this code to create the field:

var body_data = ‘{ “name”: “My OnInstall”, “description”: “Custom field for integration”, “type”: “com.atlassian.jira.plugin.system.customfieldtypes:textfield”, “searcherKey”: “com.atlassian.jira.plugin.system.customfieldtypes:textsearcher” }’;
var response = await api.asApp().requestJira(route/rest/api/3/field, {
method: ‘POST’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: body_data
});

Anything else I can try?

@KishoreMandyam,

When you create a field with the POST /rest/api/3/field API, using a type like com.atlassian.jira.plugin.system.customfieldtypes:textfield, then you create a regular built-in custom field. The API for Forge fields will not work for such a field, because that API is reserved for Forge fields from your app (not regular fields created by your app the way you are doing, but for fields or field types that your app provided in the manifest), and your field is not a Forge field.

Ah OK, that makes sense. So I guess the only way to create a field that I can update via the Forge API is by creating it in the manifest? But such a field is not usable in Automation, as I have posted in another question. Automation is critical to what we do, since we need to updates from Jira back to our system. Are there no other options?

Here’s that other question I have raised: Forge Package Custom Field not found in Automation

Also, @kkercz, are there other ways I can update a field that I create within the app? I understand I can’t use a Forge API. What else could I do to update the field, then? I’m sorry I’m asking what may be a Jira API 101 question, I’m obviously confused with all the various use-cases that the APIs support. The Edit Issue API (here: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issues/#api-rest-api-2-issue-issueidorkey-put) is not listed as a Forge API, so I’m not sure where else I should be looking.
Thanks.

You are right, @KishoreMandyam, Forge fields are not fully supported in Automation at this point. We want to change this in the future, but I can’t share any dates yet.

To update fields (including fields you created yourself as you described), you can use the Edit issue API.

@kkercz The Edit Issue API does not work on the field that my code creates, as I said in my recent post. I create the field in this manner:

var body_data = { "name": "My Field OnInstall", "description": "Custom field for my integration", "type": "com.atlassian.jira.plugin.system.customfieldtypes:textfield", "searcherKey": "com.atlassian.jira.plugin.system.customfieldtypes:textsearcher" };
response = await api.asApp().requestJira(route/rest/api/3/field, {
method: ‘POST’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: body_data
});

This gives me field info, as designed. I then assign the field to the default screen in this manner:

var r_add_fld = await api.asApp().requestJira(route/rest/api/3/screens/addToDefault/customfield_10051, {
method: ‘POST’,
headers: {
‘Accept’: ‘application/json’
}
});

This works well. I now have a field that I can see in Jira and add into an Automation. And I can edit the field value in Jira. But, I can’t add data into the field via the API. For example, I do this, as shown in the EDIT API documentation:

var bodyData = { "update": { "customfield_10051": [ { "set": "50028SjQAAV" } ] } };
const r1d1 = await api.asUser().requestJira(route/rest/api/2/issue/10091 , {
method: ‘PUT’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: bodyData
});

And this is the response:

{
message: ‘Authentication required’,
name: ‘NEEDS_AUTHENTICATION_ERR’,
status: 401,
serviceKey: ‘atlassian-token-service-key’
}

I have tried this with the “edit” keyword instead of “set”, makes no difference. I have tried asApp() instead of asUser() and that gives me this helpful message:

{“headers”:{},“ok”:false,“status”:400,“statusText”:“Bad Request”}

I have tried other APIs too, as I have described in my previous post. What am I doing wrong?

Could you try sending this payload to the edit issue API?

{
  "fields": {
    "customfield_10051": "50028SjQAAV"
  }
}

That should work assuming that you are correctly authenticated (unfortunately the 401 status code in the response would indicate that the request for some reason wasn’t, it looks like it should work with at least asApp(), though).

@kkercz I’d tried that earlier, tried again, doesn’t help.
My code:

var bodyData = ‘{ “fields”: { “customfield_10053”: “5002800000JnSjQAAV” } }’;
const r1d1 = await api.asApp().requestJira(route/rest/api/2/issue/10094, {
method: ‘PUT’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’
},
body: bodyData
});
console.log(update response via edit-issue: ${JSON.stringify(r1d1)});

Shows me:

update response via edit-issue: {“headers”:{},“ok”:false,“status”:400,“statusText”:“Bad Request”}

Strange thing: I added a custom field from the Jira front-end. I can’t update that either, from the API. Is that not supported?

Here’s the field definition (its configuration is identical to that of the API-added field):

{
“id”: “customfield_10054”,
“key”: “customfield_10054”,
“name”: “My Ext Id”,
“untranslatedName”: “My Ext Id”,
“custom”: true,
“orderable”: true,
“navigable”: true,
“searchable”: true,
“clauseNames”: [
“cf[10054]”,
“My Ext Id”,
“My Ext Id[Short text]”
],
“schema”: {
“type”: “string”,
“custom”: “com.atlassian.jira.plugin.system.customfieldtypes:textfield”,
“customId”: 10054
}
}