# Failure modes

The production failures this skill exists to catch, grouped by where they start. Each block gives what happens, why, how to detect it (audit rule IDs in brackets), how to prevent it and how to repair it. Rules are explained in [reading-the-crm.md](reading-the-crm.md).

## Stage model

FM01 Lifecycle carries follow-up or product state

- What: values such as Recycled, Disqualified, Trial or Churned in lifecycle, or workflows moving lifecycle back to Lead on recycle.
- Why: one field is asked to answer four questions.
- Detect: unknown values (T02); backward moves by automated sources (T03); re-entry loops (T10); nobody can answer "is this a customer" from one field.
- Prevent: the four-field model; recycle on the follow-up field with a reason and a recycle date; product state in its own properties.
- Repair: map old values to the right field through the change list with the cohort; keep history; restate funnel definitions with an effective date.

FM02 A recycle or correction write silently does nothing

- What: a workflow "sets" an earlier lifecycle value, the action runs, and the value stays.
- Why: HubSpot imports, forms, the API, workflows and the Salesforce integration only move lifecycle forward. An earlier value needs clear, then set (Professional or Enterprise).
- Detect: follow-up status says recycled while lifecycle stays MQL or later; workflow history shows the action, property history shows no change.
- Prevent: never recycle through lifecycle; one governed correction workflow with a correction reason property.
- Repair: a governed clear-then-set for an approved cohort, then review stage-date reports.

FM17 Recycle loop

- What: the same records re-qualify again and again.
- Why: recycle without a recycle date or re-entry evidence; engagement inputs that never expire.
- Detect: T10.
- Prevent: re-entry only on a new request or evidence dated after the recycle date; windows on every engagement input.
- Repair: hold looping records out of the queue until new evidence arrives.

FM20 Lead pipeline automation stalls after a manual back-move

- What: HubSpot leads stay in New although reps are working them.
- Why: a lead moved back by hand is not moved forward by later activity, and automation runs only in the default lead pipeline.
- Detect: leads in New or Attempting with later outreach or connected activities; leads in custom pipelines expected to progress automatically.
- Prevent: no manual back-moves; disqualify and create a new lead for a new episode.
- Repair: move affected leads to the stage their activities show, through the change list.

## Writers

FM03 Writer ping-pong on stage or owner

- What: two systems keep flipping a value.
- Why: two automated writers with no precedence, or a sync and a user disagreeing.
- Detect: T05; property history sources alternate on the same field.
- Prevent: one automated writer; others propose through a separate field or a task; integrations write only permitted fields.
- Repair: stop or narrow the writer first, then restore values from the history export for the affected cohort.

FM04 A writer sets a value it should not

- What: a copied form with its lifecycle setting at Customer, a billing sync writing lifecycle, an import setting MQL, a warehouse job setting deal stage.
- Why: writer permissions defined per field, not per value; form settings travel with the copy.
- Detect: value-level unexpected writer (T06); gate violation (T04).
- Prevent: a value-level writer list; review the lifecycle setting on every form copy; review integration field lists against the register.
- Repair: fix the producer, correct the cohort through the correction path, and review tasks, emails and reports that already reacted.

FM05 An integration update reassigns a Salesforce Lead

- What: the owner changes seconds after an enrichment or sync update.
- Why: REST creates and updates apply the active assignment rule unless the request sends `Sforce-Auto-Assign: FALSE`; omitting the header means TRUE.
- Detect: Owner history rows by the integration user within seconds of its own field updates; owner changes with no routing reason.
- Prevent: integration updates send `Sforce-Auto-Assign: FALSE`; SOAP and Bulk API apply a rule only when the call names it, so check each path ([platform-mechanics.md](platform-mechanics.md)); one integration user per integration.
- Repair: stop the writer, then restore owners from history for the affected Leads; keep received_at.

FM22 Writer inventory incomplete

- What: the register misses a writer that keeps changing values.
- Why: the HubSpot CLI lists v4 flows only; integrations and imports never appear in workflow lists.
- Detect: history sources name writers absent from the inventory (T06 INFO line).
- Prevent: build the inventory from history sources first, configuration second.
- Repair: add the writer to the register and decide allow, narrow or stop.

## Routing and clocks

FM06 Rotation churn and unowned requests in HubSpot

- What: accepted requests move between reps; some requests end with no owner.
- Why: filter-based re-enrollment (company size changed) reruns rotation with overwrite on; "Assign to available users only" with every user Away leaves leads unassigned; no eligible user leaves records unowned; editing the owner list resets counts; lead rotation needs "Sync lead owner with contact or company owner" off; Salesforce owner sync can write the previous owner back.
- Detect: owner churn (S05); unowned or assigned after the class limit (S07); ping-pong on owner fields (T05); distribution counts after owner list edits.
- Prevent: enroll on the new-request event; overwrite off for accepted requests; a no-owner branch to a named fallback; an unowned view checked hourly during coverage.
- Repair: reassign through the change list; keep received_at.

FM07 SLA measured on the owner clock

- What: the dashboard shows fast responses while buyers wait.
- Why: HubSpot Lead response time runs from assignment to the current owner's first interaction, resets on reassignment and counts marking a task in progress.
- Detect: S06; compare the native report with the buyer clock.
- Prevent: the buyer clock is the SLA; the owner clock is a coaching metric labelled as one.
- Repair: restate the SLA report with an effective date.

FM08 The clock starts at CRM creation

- What: integration and batch delay disappear from the SLA.
- Why: middleware batches, the Web-to-Lead pending queue (CreatedDate later than submission past the daily limit), imports, enrichment waits.
- Detect: received-to-CRM lag (S04); Web-to-Lead bursts after the daily limit.
- Prevent: capture received_at at the source; push each submission on receipt.
- Repair: backfill received_at from the form tool's submission log where it exists; label older data.

FM09 Unanswered requests excluded

- What: compliance is computed over answered requests only.
- Why: reports built as a median of responded requests.
- Detect: S02 against the answered-only rate; S03.
- Prevent: the denominator rule; a not-yet-due category; age stored for open requests.
- Repair: restate past reports with the rule.

FM10 A repeat request overwrites one timestamp

- What: a second demo request has no SLA record.
- Why: contact-level timestamp fields; HubSpot workflows enroll once unless re-enrollment is designed, and a record still enrolled does not start again.
- Detect: more requests than SLA records per contact; latest form submission newer than "first contacted".
- Prevent: a request record or ledger with its own ID; event triggers; designed re-enrollment.
- Repair: rebuild request records from the form submission log for the window.

FM11 Hand-raise blocked by score or enrichment

- What: demo requests wait for a score threshold or an enrichment response.
- Why: hand-raises treated as points; enrichment without a timeout.
- Detect: hand-raise requests in S03; enrichment timeouts before assignment.
- Prevent: the hand-raise bypass; an enrichment timeout with a fallback; exclusions only.
- Repair: route the backlog through the fallback owner.

FM12 Existing relationship routed to new-business rotation

- What: a customer or an open-opportunity contact lands with a new rep.
- Why: relationship checks run after distribution, or cannot run at all: Salesforce Leads have no AccountId before conversion, so native assignment rules cannot keep the open opportunity or account owner unless a lead-to-account match (by email domain or a matching tool) writes the matched account and its owner onto the Lead before the rules run.
- Detect: assigned owner differs from the account or open opportunity owner without a rule reason.
- Prevent: relationship checks first, with the lead-to-account match ahead of Salesforce assignment rules; a covering rep while the owner is away, with account ownership unchanged.
- Repair: return the request to the relationship owner and record the reason.

FM24 Queue ownership counted as assignment

- What: Salesforce Leads sit in a queue while reports and S07 show them assigned.
- Why: assigned_at taken from the first owner change, which can be a queue (OwnerId starting 00G rather than 005).
- Detect: owner history whose first value is a queue; requests whose only owner change is to a queue.
- Prevent: assigned_at is the first change to a user; a queue counts only when it is staffed and has its own pickup SLA in the register.
- Repair: rebuild assigned_at from the first change to a user and re-run S07.

FM25 Self-booked meetings miscounted

- What: hand-raise compliance looks perfect, or S03 and S07 fill with requests the buyer already booked.
- Why: a booking at submission is counted as a zero-minute response, or as unanswered.
- Detect: hand_raise requests with meeting_booked_at equal to received_at; first_response_at equal to a scheduler confirmation.
- Prevent: the booked_at_submit class with its own stop event (a personal confirmation before the meeting, or the meeting held); a booking never stops the hand_raise clock.
- Repair: reclassify booked requests and restate R03 with an effective date.

FM26 Two request records for one buyer action

- What: one demo request creates two HubSpot leads, two SLA rows (hand_raise and mql) and two queue items, and the second lead often has no owner.
- Why: an intake workflow creates a lead for the submission, and the lead pipeline's "Create a lead" automation creates another when the same submission makes the contact an MQL. HubSpot's lead automation page documents no duplicate check (page updated 2026-08-10).
- Detect: leads for the same contact created within a minute of each other (a leads export with the associated contact ID and creation source); an mql request and a hand_raise request for the same contact with the same received_at; lead creation counts above request counts.
- Prevent: one request record per buyer action; an MQL reached through a hand-raise is decided on the hand-raise's record; in HubSpot, the Create a lead automation stays off when workflows create leads.
- Repair: keep the intake lead, which holds the submission ID and received_at; move any decision onto it; disqualify the duplicate with a duplicate reason through the change list and set excluded_reason duplicate for it in the requests file; restate R03 with an effective date.

## Handoffs and renewals

FM13 Required stage properties assumed to guard every writer

- What: closed-won deals reach customer success with empty packet fields.
- Why: HubSpot documents required stage properties for manual creates and moves in the UI only.
- Detect: closed-won deals with empty packet fields where the source is an import, integration, workflow or API.
- Prevent: a per-stage exception view checked daily; checks inside each writer.
- Repair: complete the packet before the customer success clock starts; record the delay.

FM15 Customer state misread from billing

- What: Customer set before any payment, or access treated as paid.
- Why: Stripe send_invoice subscriptions without a trial start active even when the first invoice is unpaid; payment methods with delayed confirmation, such as ACH Direct Debit, can make a subscription active while the payment is processing, and if that payment fails Stripe voids the invoice while the subscription stays active. Active does not mean every invoice is paid.
- Detect: Customer set by a billing source while the first invoice is open or voided; customers whose subscription is active with no paid invoice.
- Prevent: billing writes customer state fields; Customer comes from closed won or the paid billing state, defined as the invoice status paid (invoice.paid), read from the invoice, never the subscription status alone.
- Repair: correct through the correction path; restate the customer count.

FM18 Closed-won lost between sales and customer success; renewal unowned

- What: no customer success owner, no acceptance, renewals found after the notice deadline.
- Why: no acceptance step; renewal tracked as one date on the company.
- Detect: customers without a customer success owner 2 business days after close (the closed-won SLA); cycles inside the review window with no owner, next action or due date; decisions recorded after the notice deadline; self-serve exceptions (failed payments, scheduled cancellations, downgrades) with no owner.
- Prevent: a handoff gate with acceptance; one renewal cycle record per cycle with separate commercial, billing and access states.
- Repair: assign owners to open cycles first, oldest notice deadline first.

FM21 Salesforce conversion drops request context

- What: the new opportunity carries an older request's source, or none.
- Why: conversion fills empty fields only on existing Contacts and Accounts; the most recently associated campaign becomes Primary Campaign Source; Email Opt Out and Do Not Call are not updated on an existing Contact.
- Detect: opportunity acquisition fields blank or older than the converting Lead's request.
- Prevent: map request-level fields to the Opportunity; keep a request ledger.
- Repair: backfill opportunity acquisition fields from the converted Lead records.

## Reporting

FM14 Stage calculated properties off for new stages

- What: velocity and aging reports are blank or wrong for recently added stages.
- Why: HubSpot turns stage calculated properties off by default for new pipelines and stages.
- Detect: records currently in a stage with no Date entered value.
- Prevent: turn them on when a stage is created (Edit property settings or Super Admin).
- Repair: turn them on; HubSpot fills values retroactively. Re-run the report.

FM16 Funnel counts occupancy or immature cohorts

- What: teams report different MQL numbers for the same month.
- Why: one report counts records currently in a stage, the other counts entries; rates computed before the window closes.
- Detect: "currently MQL" against "entered MQL in the period"; rates on cohorts whose window is still open.
- Prevent: entry cohorts with a maturity rule.
- Repair: publish one definition in metrics.md with an effective date.

FM23 Deals without contacts or contact roles

- What: deals close while contact lifecycle never reaches Opportunity or Customer, and person-level conversion is undercounted.
- Why: deals created without associated contacts; Salesforce opportunities without an OpportunityContactRole, which HubSpot's Salesforce opportunity sync needs before it moves contact lifecycle.
- Detect: count open and won deals with no associated contact (a deals export with associated contact IDs, or the MCP read tools with associations requested; verify the parameters at run time) and opportunities with no contact role (`SELECT Id FROM Opportunity WHERE Id NOT IN (SELECT OpportunityId FROM OpportunityContactRole) AND CreatedDate >= <window start> LIMIT 2000` through soqlQuery). Report a count, a rate and example IDs.
- Prevent: the SDR to AE packet requires the buying contact on the deal or as a contact role; a daily exception view lists deals without one.
- Repair: associate the contacts or add the roles through the change list, then restate R01 for the affected cohort.

## Evidence and history

FM19 History quietly incomplete

- What: audit counts look clean because history is missing.
- Why: revision caps (45 per contact property, 20 for other objects), Salesforce field history tracking off, the CLI excluding CRM_UI by default, the HubSpot MCP server having no history tool, Sensitive Data blocking activities.
- Detect: T01 (on export files; a warehouse history table landed continuously is not capped, so set its revision_caps to null rather than read a cap warning as missing history); empty Salesforce history for an untracked field; CLI output with no CRM_UI rows; zero activities through MCP while reps are working.
- Prevent: land history in the warehouse on a schedule; turn on tracking for Status, Owner and StageName (check the field limit); always use `--include-ui`.
- Repair: label affected metrics incomplete; exclude capped records from transition counts.
