trying to update a custom field in a table that extends sc_cat_item

Renee-17
Tera Guru
  • Help!
  • I have a table that I will call x_product that extends sc_cat_item.  There is a custom field quantityonstock that exists on the x_product table in a scoped app. 
  • I have not been able to update the field using a script include. 
  • Currently, quantityonstock is successfully updated via a server side script that's part of a widget and also via a scheduled import and via a backend script. But I need to be able to update it via a script include.
  • I know that the code works as I have tested it via backend script.
  • I've looked into Application Access, Cross Scope Privileges, Restricted Caller Access, Read-Only on field, ACLs, Don't see any Data policies.  Not sure what I'm missing. 

___________________________________________________________________

Here's a little more detail with screen shots:

 

Ultimately, I want to be able to call the Script Include from UI Builder Experience Page via Data Transform Server Side Script.

 

Current setup is a Fix Script that calls a Script Include in WMS scope

Fix Script calling Script Include.png

 

The Script Include is in the same WMS scope but updates a table in another scope.  We'll call the scope ABC.

Script Include heading screenshot.png

 

Here's a snippet of the code:

var processInventoryUtility = Class.create();
processInventoryUtility.prototype = {

    initialize: function(productSysId, quantity) {
        this.qty = parseInt(quantity, 10);
        this.productId = productSysId;
    },

    //Retrieve Record
    _retreiveRecord: function() {
        var productGr = new GlideRecord('x_products');
        var results = {
            productcode: null,
            currentQty: null
        };
        if (productGr.get(this.productId)) {
            results = {
                productcode: productGr.getValue('productcode'),
                currentQty: parseInt(productGr.getValue('quantityonstock'), 10)
            };
            return results;
        }
        return results;
    },

    //Update Record
    _updateRecord: function(vnewQty) {
        var productGrUpd = new GlideRecord('x_products');
        if (productGrUpd.get(this.productId)) {
			gs.info('New value for productcode(' + productGrUpd.getValue('productcode') + ') = ' + vnewQty.toString());
            productGrUpd.setValue('quantityonstock', vnewQty.toString());
            var updResult = productGrUpd.update();
			gs.info('updResult: '+ updResult);
			gs.info('Updated the Record!');
        }
    },

    //Zero Out Quantity
    zeroOutQty: function() {
        var response = this._retreiveRecord();
        gs.info('response.currentQty =' + response.currentQty + ' for productcode ' + response.productcode);
        if (response.productcode) {
            const newQty = 0;
            this._updateRecord(newQty);
            return 'Record Found and Zeroed out for productcode ' + response.productcode;
        }
        return 'Record Not Found for sysid ' + this.productId;
    },

    type: 'processInventoryUtility'
};
  • After running the fix script, when I view the record in the x_product table, it is unchanged. 
  • x_product is in the ABC scope. 
  • Please note that I can update a different custom table in the scope. 
  • This x_product table is an extension of the sc_cat_item table, but the quantityonstock field is only in the x_product table as a custom string field.

 

I'm able to see that the record is found but the update statement returns null.  See updResult in the system log below.  There are not errors. 

Renee17_0-1767719028231.png

 

I can run the update portion of the script include with no problems from Background Scripts.  But my understanding is that security posture is not as tight when running scripts in background scripts.  I am running the script as WMS scope. (Below is a snippet of what I run in background script).  My understanding is that this loose security posture holds true for imports also, as our transform map is able to update quantityonstock  based on data provided in a file.

	var productGrUpd = new GlideRecord('x_products');
        if (productGrUpd.get('b829d27047d5ee50d56a0f6ba26d4346')) {
            productGrUpd.setValue('quantityonstock', '0');
            var updResult = productGrUpd.update();
			gs.info('updResult: '+ updResult);
			gs.info('Updated the Record!');
        }

 
Note:  I also can't update the field when viewing the list.  No matter if I am in WMS or ABC scope.

Renee17_1-1767720286508.png

 

I've also switched everything from WMS scope in terms of the script include and the fix script and created the same version of it under the ABC scope and still get the same results - No update happens.

 

  • The field is not read-only
  • I've checked business rules on both the x_products table and the table it extends sc_cat_item.  The only business rule I see is global is to prevent an update when the record is checked out.  We don't use this field and it is currently blank for all records in the x_products table.
  • I've performed the cross-scope privileges.  
  • I've checked that the table allows for accessibility from All application scopes where caller access is None and can read/create/update/delete are all checked.  Allow access to this table via web services and allow configuration are all checked.
  • I did find something interesting in Form Builder that I hadn't seen before and wondering if this is the culprit.  Attributes for the quantityonstock shows edge_encription_enabled=true.  However if you view the  Dictionary Entry for quantityonstock, it is empty under the attribute field.  I only see it when viewing it in Form Builder as show below.

Renee17_2-1767721577611.png

Renee17_0-1767723852491.png

 

Could the edge_ecryption_enabled=true be my issue or some other type of security attribute or something special about extending from sc_cat_item?  (NOTE: Don't think its related to edge_ecryption_enabled as we don't have it setup in our instance.)

 

Thanks in advance for your help on this topic!

3 ACCEPTED SOLUTIONS

Ankur Bawiskar
Tera Patron

@Renee-17 

script include is in which scope? if same then you should be able to update.

share some screenshots.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

Sandesh Powar
Tera Expert

Hey @Renee-17 ,

Thanks for all those detailed screenshots and info - that really helps! Based on everything you've shared, I think I've spotted your issue.

The Problem: You're getting null on the update, which in ServiceNow typically means the update was blocked by an ACL (Access Control List) specifically for write operations.

Here's what's interesting - you mentioned you can't update the field even from the list view, which is a dead giveaway that there's a write ACL blocking you.

Here's what to check:

  1. Field-Level ACLs - This is most likely your culprit:
    • Go to System Security > Access Control (ACL)
    • Filter by: Name = x_products.quantityonstock AND Operation = write
    • Check if there's an ACL that's denying write access
    • Look at the Condition and Script fields - there might be logic preventing updates
  2. Table-Level Write ACLs:
    • Also check for ACLs on x_products table with operation = write
    • And check the parent sc_cat_item table too since you're extending it
  3. The edge_encryption_enabled attribute - This is probably NOT your issue since you confirmed it's not configured, but it's worth noting that encrypted fields can sometimes behave oddly.

Quick Test to Confirm: Run this in Background Scripts with your WMS scope:

javascript
var gr = new GlideRecord('x_products');
if (gr.get('b829d27047d5ee50d56a0f6ba26d4346')) {
    gs.info('Can Write to table: ' + gr.canWrite());
    gs.info('Can Write to field: ' + gr.quantityonstock.canWrite());
}

If canWrite() returns false, you've confirmed it's an ACL issue.

The Fix: Once you find the blocking ACL, you'll need to either:

  • Modify the ACL condition to allow your use case
  • Add a role requirement and grant that role to the appropriate users/scripts
  • Create a new ACL with higher order that allows your specific scenario

The reason Background Scripts and imports work is because they run with elevated privileges that bypass normal ACLs. Your Script Include runs with normal security enforcement.

Let me know what you find when you check those ACLs - I'm betting that's where your answer is!


Hope this helps! If this resolves your issue, please mark it as the accepted answer so others with similar problems can find the solution easily.

Best regards!
Sandesh

View solution in original post

I was finally able to get the cross-scope update to occur.  For some reason as an admin user developing the app, when I tried to test the update, it fails.  However, if I log in as a test user that has access to the WMS App it can perform the cross-scope update.  I currently have two button set-up for testing. 

  1. One that calls a data transform server side script that calls the cross-scope script include
  2. and the other is a REST transform data broker that calls a Scripted REST Resource that calls the cross-scope script include that performs the update.

Both buttons work and perform the update for the test user account but not for my normal admin account that I'm using to develop the app, even though it contains the roles.  So there must be some ACL blocking me as an admin, but I can't figure it out.  I'm satisfied that at least I can perform the update via a test user account.

 

I did enable Debug mode and could see that the write operation was blocked but it was vague about what the ACL was.  I did update the ACL to include admin and the new rules associated with the wms app.  I ran the analyze access tool from the form view of one of the table records and saw that write and create operations are blocked by UpdateSetAccessHandler.  I'm not sure if this is related to why I can't test that piece of code with favorable results as the admin and developer.  I am able to perform other cross-scope updates without a problem, it was just this specific table.  I feel like it has something to do with the sc_cat_item table that it's extending... although it doesn't make since to me because the column I'm updating is a custom field only on the extended table.  I checked the business rules and acls on both the extended table and sc_cat_item.  

View solution in original post

12 REPLIES 12

Ankur Bawiskar
Tera Patron

@Renee-17 

script include is in which scope? if same then you should be able to update.

share some screenshots.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hi Ankur,

 

Thanks for the response.  I added more info to the post with screenshots.  I have tried to perform all from the same scope that the table is in without success.  The record is found but it will not update the field.

SohamTipnis
Tera Expert

Hi @Renee-17,

 

Can you please provide some screenshots for the whole scenario in order to go through this use case?

 

If you find my answer useful, please mark it as Helpful and Correct ‌‌😊

 

Regards,

Soham Tipnis

ServiceNow Developer ||  Technical Consultant
LinkedIn: www.linkedin.com/in/sohamtipnis10

Hi SohamTipnis,  

I added more info to the post with screenshots.  

Sandesh Powar
Tera Expert

Hey @Renee-17 ,

Thanks for all those detailed screenshots and info - that really helps! Based on everything you've shared, I think I've spotted your issue.

The Problem: You're getting null on the update, which in ServiceNow typically means the update was blocked by an ACL (Access Control List) specifically for write operations.

Here's what's interesting - you mentioned you can't update the field even from the list view, which is a dead giveaway that there's a write ACL blocking you.

Here's what to check:

  1. Field-Level ACLs - This is most likely your culprit:
    • Go to System Security > Access Control (ACL)
    • Filter by: Name = x_products.quantityonstock AND Operation = write
    • Check if there's an ACL that's denying write access
    • Look at the Condition and Script fields - there might be logic preventing updates
  2. Table-Level Write ACLs:
    • Also check for ACLs on x_products table with operation = write
    • And check the parent sc_cat_item table too since you're extending it
  3. The edge_encryption_enabled attribute - This is probably NOT your issue since you confirmed it's not configured, but it's worth noting that encrypted fields can sometimes behave oddly.

Quick Test to Confirm: Run this in Background Scripts with your WMS scope:

javascript
var gr = new GlideRecord('x_products');
if (gr.get('b829d27047d5ee50d56a0f6ba26d4346')) {
    gs.info('Can Write to table: ' + gr.canWrite());
    gs.info('Can Write to field: ' + gr.quantityonstock.canWrite());
}

If canWrite() returns false, you've confirmed it's an ACL issue.

The Fix: Once you find the blocking ACL, you'll need to either:

  • Modify the ACL condition to allow your use case
  • Add a role requirement and grant that role to the appropriate users/scripts
  • Create a new ACL with higher order that allows your specific scenario

The reason Background Scripts and imports work is because they run with elevated privileges that bypass normal ACLs. Your Script Include runs with normal security enforcement.

Let me know what you find when you check those ACLs - I'm betting that's where your answer is!


Hope this helps! If this resolves your issue, please mark it as the accepted answer so others with similar problems can find the solution easily.

Best regards!
Sandesh