Azure AD User Provisioning: cost_center (Reference Field) Not Populating Consistently

mfhaciahmetoglu
Mega Sage

Hi Everyone,

We're facing a challenging issue with our Azure AD (Entra) to ServiceNow user provisioning process, specifically when updating the cost_center reference field on the sys_user table via the Table API. We're hoping to get some insights or suggestions from the community.

 

The Core Problem:

  • The cost_center field on user records (sys_user table), which is a reference to the cmn_cost_center table, is not being populated reliably.
  • Azure AD provisioning service is supposed to send the cost_center value. We expect it to send a string (e.g., "CNF730001"), which is the code and the display value for records in our cmn_cost_center table.
  • We have verified that all cost_center string values being sent from Azure AD do exist in the code field of the cmn_cost_center table.
  • The Entra provisioning logs show a specific error for the cost_center:

    "An object in the source system has a property, the values of which are expected to match a finite set of values in the target, but a value does not match... The name of the property in the target is cost_center. The invalid value is [example_cost_center_code]. Your attribute mappings have a mapping to cost_center. cost_center has been defined as a "reference" property, whereas the source property mapped to cost_center has been defined as a "string" property... If you have chosen the "string-to-reference" property mapping correctly, then to resolve this error, update the target to include [example_cost_center_code] as a valid cost_center or update the source object to match the list of values defined in the target for cost_center."

  • This error suggests Azure is sending a string, and ServiceNow is having trouble resolving it to a valid reference, despite the value existing and being the display value.
  • Interestingly, other reference fields on the sys_user table (e.g., location) are being updated correctly through the same direct Table API mechanism, presumably also receiving string values and relying on ServiceNow's ability to look up the reference based on the display value.
  • We've compared the dictionary configuration, reference qualifiers, and display value settings for sys_user.location / cmn_location versus sys_user.cost_center / cmn_cost_center and they appear to be configured identically. The display value for cmn_cost_center is correctly set to code.

Troubleshooting Steps & Confusing Findings:

  1. ACLs: We initially found differences in write ACLs between sys_user.location and sys_user.cost_center. We aligned them by adding an admin-role write ACL to sys_user.cost_center (our integration user has admin rights). This did not resolve the issue on its own.
  2. Business Rule for Debugging & Processing: We implemented a "Before Insert/Update" Business Rule on sys_user with a high order to:
    • Log the incoming value for cost_center.
    • Attempt to look up the sys_id in cmn_cost_center using the incoming string (assuming it's the code).
    • If a match is found, explicitly set current.cost_center to the sys_id.
  3. Contradictory Business Rule Logs:
    • This is the most puzzling part: Our BR logs show that for cost_center (and the working location field), ServiceNow is actually receiving the sys_id of the cmn_cost_center record directly in current.cost_center.toString() before our script even performs its lookup.
    • This directly contradicts the Entra error message, which implies it's sending a string value and failing on the string-to-reference conversion.
  4. Business Rule "Effectiveness":
    • When the BR runs for users who already have a cost_center and are being updated, the field seems to be correctly populated/maintained (likely because the sys_id is already there, or our script re-confirms it).
    • However, a test case involving changing the cost_center in Azure for an external (EXT) user who did not have one previously, or had a different one, did not result in any update being received in ServiceNow (no logs from our BR for this user, no update to the user record).
  5. Sporadic Updates & Error Shifting:
    • The update timestamps for users who do get updated are sporadic (e.g., :53, :54, :56 past the hour) and don't align with our standard 40-minute Entra provisioning cycle.
    • For a few EXT users where the cost_center did eventually get populated, we now see the exact same Entra error message but for the department field (another reference field).

Our Key Questions for the Community:

  1. Entra Error vs. ServiceNow Logs: How can Entra report sending a string and failing on "string-to-reference" conversion, while our ServiceNow BR logs (and current.cost_center.toString() before our logic) show a sys_id being received for cost_center? Is there an intermediate Azure process, or could the sys_id be sent alongside the string, causing confusion?
  2. Initial Failure: If Azure is sending the sys_id (as per BR logs), why would the update fail for cost_center initially (necessitating the BR workaround attempts) and why would Entra log the specific "string-to-reference" error?
  3. Inconsistent Behavior: Why does the cost_center update work for some users (those already with values) but fail for new users or when a value is changed for specific test users (the EXT user example)?
  4. Sporadic Syncs: Any ideas why the updates are not consistently following the 40-minute sync cycle?
  5. Error Shifting: Why might the error shift to the department field once cost_center is (partially) resolved for some users? Does this point to a more general issue with how our Entra > ServiceNow provisioning handles certain reference fields?
  6. cost_center vs. location: Given seemingly identical setups and both apparently receiving sys_ids (according to BR logs for incoming values), what could make cost_center problematic while location works fine through the direct Table API update? Are there any subtle attributes, dictionary settings, or specific behaviors related to cmn_cost_center that might interfere with API-based reference resolution, even when a sys_id is provided?

We are looking for any insights, similar experiences, or troubleshooting avenues we might have missed. This inconsistent behavior and conflicting information are making it very difficult to pinpoint the root cause.

Thanks in advance for your help!

7 REPLIES 7

Sure, so let's watch out for a short-term solution. Can you maybe share some details about your Business Rule, like the code and the header data?

Br

Stefan

Hi Stefan, 

 

Sure. 

 

(function executeRule(current, previous /*null when async*/) {

        var costCenterInput = current.cost_center.toString().trim(); // Get the incoming value and trim spaces

         gs.info("BR 'Resolve Cost Center from Azure AD API': Received cost_center input: " + costCenterInput); // For debugging

		 gs.info("BR what about the location field: " + current.location);

        var grCostCenter = new GlideRecord('cmn_cost_center');

  
        grCostCenter.addQuery('sys_id', costCenterInput); // 
        grCostCenter.query();

        if (grCostCenter.next()) {
            current.cost_center = grCostCenter.sys_id; // Set to the sys_id of the found record
             gs.info("BR 'Resolve Cost Center from Azure AD API': Resolved to sys_id: " + grCostCenter.sys_id + ' for user: ' + current.user_name + ' ' + current.name);
        } else {
            gs.warn("BR 'Resolve Cost Center from Azure AD API': Cost Center code '" + costCenterInput + "' not found in cmn_cost_center for user: " + current.user_name + ". Clearing or leaving as is.");        
    }

})(current, previous);

I have this simple BR on before triggered when "updated by"  is the azure user.

I see that the debugs and it is constantly being triggered by the user records that are already on the system. Such as:

BR 'Resolve Cost Center from Azure AD API': Resolved to sys_id: da07727697c7f5903eb5b741f053af8c for user: 1000xxxx Laiza XXX

--> This record was already on our user table and I have no idea why the BR is triggered for this.

 

But I had one user which was created new from Azure side and for this one I received no cost center. 

 

Best,

Firat

 

Kim Sullivan
Tera Guru

What's also confusing, is in the Identity Provider record, you have a Related link to User Provisioning Transform Map.  And that seems to do nothing -- so why is it in there?  It would be great, if that was the ACTUAL transform map for the users and you could make adjustments to it as needed.

 

Created an Idea -- please vote.  Thanks.  https://support.servicenow.com/ideas?id=view_idea&sysparm_idea_id=cdebe68d87e2ae1457288519dabb3523&s...