- Fix Guides
- How to Fix HubSpot Contact Merge Failures
How to Fix HubSpot Contact Merge Failures
Step-by-step fix guide with AI-powered diagnosis from BuildForce.
HubSpot contact merges fail when the two contacts have conflicting calculated properties (lifecycle stage that has progressed in one but regressed in the other), when one contact is the primary on a deal or company that the secondary can't inherit, when the secondary is referenced by an active workflow enrollment, or when API merge calls hit the wrong endpoint version. The fix is to inspect both contacts' associations and calculated properties, pick the primary contact deliberately (it inherits the secondary's history but keeps its own property values for non-blank fields), and use /crm/v3/objects/contacts/merge with the correct objectIdToMerge.
Symptoms
Merge dialog showing 'Unable to merge — contacts cannot be combined' with no specific reason
POST /crm/v3/objects/contacts/merge returning 400 with 'OBJECT_NOT_FOUND' or 'INVALID_MERGE'
Lifecycle stage of the primary contact regressing after merge (e.g., Customer → Lead)
Custom calculated properties showing the wrong value post-merge
Associated deals or companies disappearing from one contact after the merge
Workflow re-enrolling the merged contact unexpectedly into a stale enrollment
Root Causes
Lifecycle stage cannot regress
HubSpot enforces a 'lifecycle stage can only move forward' rule. If contact A is at 'Customer' and contact B is at 'Lead', merging B into A keeps Customer — but merging A into B regresses to Lead and the platform blocks the merge unless you clear the stage on the primary first.
Active workflow enrollment on secondary
If the contact being merged into the primary is actively enrolled in a workflow with re-enrollment disabled, the merge fails because HubSpot can't transfer the enrollment cleanly. Unenroll from active workflows before merging.
Calculated property reconciliation conflict
Calculated properties (HubSpot score, custom calc properties) recompute post-merge based on the primary's data. If the secondary held the value that drove the calculation, the merged record's score can drop unexpectedly.
Primary email collision
When both contacts have a primary email (the canonical 'email' property), HubSpot keeps the primary contact's email and moves the secondary's email to the 'Additional emails' set. If your downstream integration only reads the primary email field, you lose addressability.
Wrong API endpoint or payload shape
The /crm/v3/objects/contacts/merge endpoint expects {primaryObjectId, objectIdToMerge}. Using the older /contacts/v1/contact/merge or swapping the IDs results in 400 errors or unintended primary selection.
How to Fix It — Step by Step
Identify both contacts' associations before merging
Pull both contacts with their associations to deals, companies, tickets, and engagements. The merge will move all associations to the primary, but you need to confirm there are no duplicates that will create stale links.
GET /crm/v3/objects/contacts/{contactId}?associations=deals,companies,tickets&properties=email,lifecyclestage,hs_lead_statusPick the primary contact deliberately
The primary contact's property values win for any field where both contacts have a non-blank value. Pick as primary the contact with: the most recent activity, the further-progressed lifecycle stage, and the canonical email you want to keep as the main address.
Unenroll from active workflows on the secondary
Before calling merge, remove the secondary contact from any active workflow enrollments. Use POST /automation/v2/workflows/{workflowId}/enrollments/contacts/{contactId}/unenroll for each blocking workflow. This is the single most common cause of merge 400s.
Clear conflicting lifecycle stage on the primary if needed
If the primary needs to take on the secondary's stage (rare — you should usually pick the more-advanced contact as primary), clear the primary's lifecycle stage before merging. HubSpot will then accept the secondary's value during the merge.
PATCH /crm/v3/objects/contacts/{primaryId}
{
"properties": { "lifecyclestage": "" }
}Call the v3 merge endpoint with correct payload
Issue the merge via the v3 endpoint with primaryObjectId and objectIdToMerge. The objectIdToMerge contact will be archived (not deleted) and accessible via GET with archived=true for 90 days.
POST /crm/v3/objects/contacts/merge
{
"primaryObjectId": 123,
"objectIdToMerge": 456
}Verify post-merge property values and associations
Fetch the merged primary contact and audit: primary email, lifecycle stage, custom calculated properties, and association counts. Compare against the pre-merge snapshot to confirm nothing dropped unexpectedly.
Configure prevention: deduplication tool + integration upsert keys
Run the HubSpot Duplicates tool weekly. In every integration writing to HubSpot, set the matching key to email (or a custom unique-ID property) so new records upsert against existing contacts instead of creating duplicates that need merging later.
Let BuildForce diagnose and fix this automatically
Instead of following manual steps, connect your org and let our AI identify exactly what's broken and how to fix it — in minutes.
Book a DemoCommon Questions
More answers about this issue and how to resolve it.
Stop debugging manually. Let AI do it.
BuildForce runs 200+ automated checks across your Salesforce org and tells you exactly what's broken and how to fix it.