Azure AD User Provisioning: cost_center (Reference Field) Not Populating Consistently
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-20-2025 05:23 AM - edited 05-20-2025 05:23 AM
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:
- 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.
- 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.
- 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.
- 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).
- 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:
- 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?
- 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?
- 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)?
- Sporadic Syncs: Any ideas why the updates are not consistently following the 40-minute sync cycle?
- 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?
- 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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-20-2025 07:57 AM
Just a question to be clearer about the issue: Why was it necessary to use the Table API instead of more reliable and recommended methods like a Data Stream + Flow, or at least using an Import Set with a Transform Map attached?
Without knowing your specific requirements or past considerations, it looks to me like the interface could be designed in a more manageable (and more recommended) way. The Table API in particular is something that should usually not used for data synchronization.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-20-2025 09:32 AM
Hi @Stefan Reichelt ,
Many thanks for the reply.
By Table API, I meant the standard procedure for enabling user provisioning for ServiceNow, described on the official documents: https://learn.microsoft.com/en-us/entra/identity/saas-apps/servicenow-provisioning-tutorial
Best,
Firat
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-20-2025 01:36 PM - edited 05-20-2025 01:37 PM
I see, that interface is actually using the Table API which is still not the best way to import users. Do you maybe have an IntegrationHub subscription which has the Entra ID Spoke integrated? That would allow you to configure it in ServiceNow, including a proper mapping within a Flow.
Another method:
SAML user provisioning - Support and Troubleshooting
Related Community discussion:
How to do Entra (Azure AD) user provisioning for m... - ServiceNow Community
At the end of the day, I would recommend to prefer a method which allows you to stage and map the data properly before they enter the User table. If you use a Transform Map, you don't need any Business Rule to translate field values. Instead, you can use OOB ways to map data exactly as you want. You can even script everything for each mapped field separately.
Br,
Stefan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-21-2025 01:36 AM
Hi Stefan,
Thanks a lot for the suggestion. I agree that allowing for a Transform map would make everything much easier, but changing the entire integration structure is not feasible for us now. That's why we are trying to understand the inconsistent behaviour coming from the current integration.
Best,
Firat