- Fix Guides
- How to Fix HubSpot Deal Pipeline Misalignment
How to Fix HubSpot Deal Pipeline Misalignment
Step-by-step fix guide with AI-powered diagnosis from BuildForce.
HubSpot deal pipeline misalignment shows up as wrong forecast numbers, deals stuck in the wrong stage, or stage probabilities that don't reflect actual conversion rates. The fixes: recalibrate each stage's win-probability based on the last 12 months of closed/won data, ensure custom pipelines have unique internal IDs (dealstage values use {pipelineId}:{stageInternalId} format), migrate deals between pipelines using PATCH /crm/v3/objects/deals with both pipeline and dealstage in the same request, and review workflow enrollments that auto-set dealstage to confirm they target the right pipeline.
Symptoms
Forecast widget showing pipeline value inconsistent with deal stage sum
Deals appearing in two pipelines after a pipeline restructure
Custom dealstage automation firing on the wrong pipeline's deals
Reports showing deals at '50% probability' that close at <10% historical rate
PATCH dealstage returning 400 with 'INVALID_OPTION' when the stage exists in a different pipeline
Sales rep view showing a stage that doesn't exist in their assigned pipeline
Root Causes
Stage probabilities never recalibrated
HubSpot defaults each stage to a probability when the pipeline is created (10%, 20%, 60%, 90%). Most orgs never update these against actual historical win rates, so the forecast widget multiplies pipeline value by stale probabilities.
Custom pipeline IDs collide on dealstage internal name
When you create multiple pipelines, each stage has an internal ID like 'qualifiedtobuy' or 'presentationscheduled'. Reusing internal names across pipelines is fine — but workflow actions and API calls that set dealstage by internal name without specifying pipelineId will pick the wrong pipeline's stage.
Pipeline migration not done atomically
Moving a deal from Pipeline A to Pipeline B requires updating both pipeline and dealstage in a single PATCH. Updating dealstage first returns INVALID_OPTION; updating pipeline first leaves the deal in stage 0 of the new pipeline regardless of where it should land.
Workflow enrollments not pipeline-scoped
Deal workflows enrolled on 'dealstage is X' without a 'pipeline equals Y' filter will fire on every pipeline that has a stage with that internal name — moving deals to the wrong pipeline or triggering wrong-pipeline notifications.
Closed-lost deals stuck in 'open' stage
Deals marked as closed-lost via a custom property without updating dealstage to a stage with closed=true still appear in the open pipeline. The forecast widget filters on stage.closed, not on a custom 'is_lost' flag.
How to Fix It — Step by Step
Audit historical win rate per stage
Pull the last 12 months of deals via /crm/v3/objects/deals/search with a closeddate filter, group by the dealstage at the time the deal closed, and calculate the actual closed-won rate. Use these as the new stage probabilities.
POST /crm/v3/objects/deals/search
{
"filterGroups": [{"filters": [
{"propertyName": "closedate", "operator": "GTE", "value": "2024-01-01"}
]}],
"properties": ["dealstage", "hs_is_closed_won", "amount"],
"limit": 200
}Update stage probabilities to match reality
In Settings → Objects → Deals → Pipelines, edit each stage and set 'Probability' to the historical win rate from step 1. Stages with <10% historical conversion should be 10% or lower regardless of where they sit in the pipeline visually.
List all pipelines and their stage internal IDs
Retrieve all deal pipelines with their stage definitions. This is the canonical reference for migration and workflow scoping — keep it in your runbook.
GET /crm/v3/pipelines/deals
// Response includes pipelines[].stages[] with { id, label, displayOrder, metadata.probability, metadata.isClosed }Migrate deals between pipelines atomically
When moving a deal from one pipeline to another, send both pipeline and dealstage in the same PATCH. Use the new pipeline's stage internal ID, not the old pipeline's.
PATCH /crm/v3/objects/deals/{dealId}
{
"properties": {
"pipeline": "default",
"dealstage": "qualifiedtobuy"
}
}Scope workflow enrollments to a specific pipeline
Open every deal workflow and add a 'pipeline is equal to X' filter to the enrollment criteria, in addition to the dealstage filter. This prevents the workflow from firing on deals in other pipelines that happen to share a stage internal name.
Force closed-lost deals into a closed stage
Run a one-time SQL-style audit via deal search to find deals with hs_is_closed_lost=true but dealstage pointing to an open stage. PATCH each one to the correct closed stage so the forecast widget excludes them.
Enable forecast variance monitoring
Track forecast accuracy weekly: compare forecasted pipeline value (sum of amount × probability) to actual closed-won. Variance >25% means stage probabilities need re-calibration. BuildForce's pipeline health check surfaces this automatically.
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.