Try Serpent Free

How to fix CANNOT_CASCADE_PRODUCT_ACTIVE in Salesforce deployments

A Product2 record can't be deactivated or deleted because an active PricebookEntry still references it.

Surfaces during: DML on Product2 records, usually in a data migration or cleanup script

What it means

CANNOT_CASCADE_PRODUCT_ACTIVE fires when an operation tries to deactivate or remove a Product2 record while it's still referenced by an active PricebookEntry. Salesforce won't cascade the change through dependent pricing records automatically, so the product stays blocked until the dependency is cleared explicitly.

It's a runtime data error, not a metadata deploy error: it happens the moment the DML statement runs, whether from Data Loader, an Apex data migration script, or a CPQ cleanup job, not during a Metadata API deployment.

Diagnosis

Common causes

Deactivation script runs before dependent pricebook entries
A data migration deactivates the Product2 record before deactivating the PricebookEntries that still point to it.
CPQ price rules still reference the product as active
Configuration in Price Rules or Bundle setup treats the product as active even after the deactivation attempt.
Migration order processes products ahead of dependents
A bulk load processes Product2 records before the Quote Line or Order Product records that still reference them.

The fix

  1. Deactivate PricebookEntries first
    Update or deactivate every PricebookEntry tied to the product before attempting to deactivate the Product2 record itself.
    List<PricebookEntry> entries = [
        SELECT Id FROM PricebookEntry WHERE Product2Id = :productId AND IsActive = true
    ];
    for (PricebookEntry pbe : entries) pbe.IsActive = false;
    update entries;
  2. Sequence CPQ migrations to detach dependents first
    Order data migration steps so bundle and price rule references are cleared before the parent product changes state.
  3. Check for active Quote Line or Order Product references
    Confirm no open Quote Lines or Order Products still point at the product before deactivating it.
In practice

How Serpent prevents this

Serpent's dependency-aware deployment sequencing applies to CPQ and pricing objects the same way it does to any other metadata, so a product deactivation and its pricebook entries move in the right order instead of colliding mid-deploy. See the Salesforce deployment error library.

Metadata and data in one deployment flow in Serpent

Prevention

Script deactivation as a single ordered job
Deactivate PricebookEntries and the Product2 record in one migration script with an explicit order, not two separately scheduled steps.
Query for dependents before every product deactivation
Make a pre-check for active PricebookEntry, Quote Line, and Order Product records a standard step in any product lifecycle automation.
Retire products through a status field, not a hard deactivation
Where the business allows it, mark a product discontinued with a custom field first and defer the actual deactivation to a scheduled cleanup once dependents are clear.
Common questions

CANNOT_CASCADE_PRODUCT_ACTIVE, answered

Can I force the deactivation anyway?
No, not directly. The dependent PricebookEntries have to be deactivated first; Salesforce won't cascade the change for you.
Does this block deleting the Product2 record too, or only deactivating it?
Both. Deleting a product with active pricebook entries fails the same way; the entries have to be deactivated or removed first regardless of which operation you're attempting.
Does this apply to the Standard Price Book entry too?
Yes. An active Standard Price Book entry blocks deactivation the same way a custom price book entry does; both have to be cleared.

Start free. No credit card, no install, no commitment.

Set up in under 15 minutes. No DevOps hire needed.

Curious about faster shipping before you dive in? Let's talk

Commitment free!