_
_
Back to Blog

Finding the Missing Assets in Your CMDB

How CI Classes, Model Categories, and a missing link create “ghost CIs” - and how to fix it with a simple script
2
min read
|
by
Ben Savage
&
Zayn Moselhy
April 7, 2026

Missing assets for some of your CIs and don’t know where to start? Read on. I’ll break it down in simple terms and give you a tool to help you remedy the situation.

The CMDB Handshake: CI Classes vs. Model Categories

At first glance, these two concepts seem to do the same thing: they categorize "stuff." However, they serve two very different masters.

1. The CI Class (The "What is it doing?")

The CI Class (sys_class_name) is a technical definition. It lives in the CMDB and tells the system what the object is and what attributes it has.

  • Focus: Operations, Discovery, and Monitoring.
  • Example: cmdb_ci_linux_server tells ServiceNow to look for RAM, CPU, and IP addresses.

2. The Model Category (The "Glue")

The Model Category is the bridge. Its primary job is to link the CI Class to an Asset Class. It dictates whether a CI should have a corresponding financial record (Asset).

  • Focus: Lifecycle management, Procurement, and Financials.
  • Example: The "Server" Model Category links the cmdb_ci_server class to the alm_hardware asset class.

How They Work Together

When you create a new CI, ServiceNow looks at its Class. It then checks the Model Categories to see if that Class is listed. If it is, the system automatically triggers the creation of an Asset. Without this link, your hardware arrives, gets discovered, but never shows up in your financial books.

The "Missing Link" Problem

Often, custom CI classes are created without a corresponding Model Category. A large number of OOTB CI classes also do not have corresponding model categories. This leads to "Ghost CIs"—technical records that exist in the CMDB but are invisible to the Asset Management team.

To maintain a healthy instance, you need to identify which CI classes are "orphaned" (configured to be tracked but missing the model category link).

Script: Identifying Orphaned and Weak CI Classes

Below is a Background Script (JavaScript) you can run to identify CI Classes that are active but do not have a defined Model Category. It then prints out the CI classes with a model category and tells you if they have an asset class. An asset class dictates that an asset record should be created!


/**
 * PART 1: Identify CI Classes missing Model Categories
 */
var ciClassGR = new GlideRecord('sys_db_object');
ciClassGR.addEncodedQuery('nameSTARTSWITHcmdb^super_class!=NULL');
ciClassGR.query();


var missingCategory = [];


while (ciClassGR.next()) {
    var className = ciClassGR.name.toString();


    var categoryGR = new GlideRecord('cmdb_model_category');
    categoryGR.addQuery('cmdb_ci_class', className);
    categoryGR.query();


    if (!categoryGR.hasNext()) {
        missingCategory.push(className);
        gs.info("❌ NO MODEL CATEGORY: " + className + " (" + ciClassGR.label + ")");
    }
}


gs.print("Total CI Classes without a model category: " + missingCategory.length);
gs.print("--------------------------------------------------");


/**
 * PART 2: Identify CI Classes WITH Model Categories & report their Asset Class
 */
var trackedClassesCount = 0;
var ciClassWithCategoryGR = new GlideRecord('sys_db_object');
ciClassWithCategoryGR.addEncodedQuery('nameSTARTSWITHcmdb^super_class!=NULL');
ciClassWithCategoryGR.query();


while (ciClassWithCategoryGR.next()) {
    var currentClass = ciClassWithCategoryGR.name.toString();


    var modelCatGR = new GlideRecord('cmdb_model_category');
    modelCatGR.addQuery('cmdb_ci_class', currentClass);
    modelCatGR.query();


    while (modelCatGR.next()) {
        trackedClassesCount++;
        // Get the label of the Asset Class (e.g., 'Hardware' instead of 'alm_hardware')
        var assetClassLabel = modelCatGR.asset_class.getDisplayValue();


        if (assetClassLabel) {
            gs.info("✅ MATCH FOUND: CI Class [" + currentClass + "] maps to Asset Class [" + assetClassLabel + "]");
        } else {
            gs.info("⚠️ WEAK LINK: CI Class [" + currentClass + "] has a Model Category but NO Asset Class defined.");
        }
    }
}


gs.print("Total CI-to-Category mappings processed: " + trackedClassesCount);

Why Run This?

  • Audit Readiness: Ensures every piece of discovered hardware is accounted for financially.
  • Data Integrity: Prevents the "duplicate" issue where assets are created manually because the auto-creation failed.
  • Process Automation: If you use Discovery, this is the only way to ensure the Discovery -> CI -> Asset flow stays unbroken.

If you want help identifying and fixing orphaned CI classes in your environment, get in touch with our team, and we’ll walk you through the script, results, and next steps to ensure your CMDB and Asset data stay fully aligned.

Written by
Ben Savage
Boston
UK-born and raised ITAM veteran now residing in Chicago.
Written by
Ben Savage
Boston
UK-born and raised ITAM veteran now residing in Chicago.
Resources

We don’t believe in hoarding knowledge

We go further and faster when we collaborate. Geek out with our team of engineers on our learnings, insights, and best practices to unlock maximum value and begin your business transformation today.

Blogresources
Explore Resources