Some links are affiliate links. If you sign up, Flowpaja may earn a commission at no extra cost to you.
A contact creation fails with a 409, so the tempting repair is to add another retry. That changes the timing of the request without changing its meaning: create a contact for an email address that already belongs to a contact. The useful question is which record the workflow should have updated.
Consider a fictional enquiry from Morgan Example. The form sends a name, an email and a project note. Morgan already exists in HubSpot because someone entered the contact last month. The automation should preserve that relationship while recording the new enquiry. Repeating the create request cannot express that intention.
Treat the conflict as evidence about identity. First establish which email was submitted, where it was mapped and which existing record HubSpot identifies. Then choose the smallest repair that preserves the right contact and its existing sales context.
Start with the failed write
Open the failed execution and inspect the input of HubSpot CRM's Create a Contact module. Copy the actual email value into your investigation notes. An email-looking question label in the form does not prove that the standard HubSpot Email property received a value.
Read the full error. If it provides an existing contact ID, open that record in HubSpot. Compare its primary email, additional email addresses and name with the submission. Do not merge contacts simply because the error contains a record ID. A merge changes the CRM's identity history and is not a routine retry strategy.
Also separate the error families. A 409 contact conflict and a 400 invalid property value require different repairs. If the latter identifies a dropdown, compare the submitted value with the property's internal option value. A visible label on a form is not necessarily the value the CRM API expects.
Choose the write behavior you need
For a workflow that handles new and existing contacts identically, Create or Update a Contact is the simpler starting point. Map the normalized email into the standard Email property, then map the fields the form is allowed to change. Make's HubSpot CRM reference lists the available contact modules.
Normalize once in concept, and use the same result for every lookup and write. lower(trim(email)) removes surrounding whitespace and case differences. Select your actual email token in Make's mapping panel; email here describes the value, not a universal field path.
Avoid replacing the email with a custom work-email field while leaving the standard property empty. The contact-matching behavior relies on the standard property. Also stop incomplete submissions before the CRM write. A nonempty, plausible email is an intake requirement; an address merely containing an at-sign is only a basic screen, not proof of deliverability.
Search first when the next action depends on newness
An upsert alone does not establish whether a Slack alert should say “new contact.” If new and existing contacts need different downstream actions, add Search for Contacts before the decision. Use an exact Email equality condition with the same normalized value. Leave a broad free-text query out of the identity lookup.
Test the no-match behavior before adding the create branch. A search that emits no bundle cannot reach a router merely because the router has a “missing ID” condition. Test whether your current HubSpot search module continues on zero results, and which supported setting or lookup response provides a bundle for that case. Do not copy Google Sheets' empty-bundle behavior onto HubSpot by assumption.
Once the search result can reach the decision, a found ID belongs on Update a Contact. A no-match path can use Create or Update a Contact to tolerate a contact that appears between lookup and write. Keep any “new person” notification policy separate from the upsert's success status.
Give the form limited authority
A resubmission might contain a better phone number. It should not necessarily replace the contact owner, lifecycle stage or carefully maintained company details. Write down which properties intake owns before mapping everything the form offers.
Make update modules skip empty mapped values by default. An unanswered optional question therefore should not be treated as an instruction to clear a known value. For deliberate clearing, use Make's erase keyword rather than an ordinary blank. Test explicit clearing on the exact HubSpot property and connector version before relying on it. Keep a fictional record for this check.
This distinction matters during repair. Mapping a fallback phrase into an empty field can make the run succeed while polluting a record. A missing phone number does not become a real phone number because the mapping inserts “Not provided.”
Inspect additional emails and overlapping runs
The contact identified by the conflict may have a different primary address. An additional email on that record can explain why a primary-email lookup found nothing but creation still collided. Review the record before deciding whether to update it. The right identity decision is more important than forcing the scenario green.
Two near-simultaneous deliveries create another gap: both lookups may happen before the first contact is visible to search. For an instant-trigger scenario, sequential processing prevents those runs from overlapping within that scenario. It does not serialize another scenario writing to the same CRM, and it does not turn the search into a database lock.
Keep the error visible if identity remains uncertain. Retry can help a temporary connection problem; the same unresolved conflict needs a changed write or an identity decision. Skip drops the failed bundle. If you choose it after an alert, someone still has to recover the missed update.
Test the relationship, not just the badge
Use a disposable contact and a fictional address such as morgan@example.invalid. Submit a new email, submit it again with changed project text, and submit it with surrounding spaces and capitals. Check that the intended contact persists and the changed field is actually present.
Then test an omitted optional field and an existing owner. Both should follow your ownership rules. If the workflow branches on newness, verify that the new-email case reaches the write and that a repeat does not receive the new-contact treatment.
Record the contact ID after each case. That gives a concrete acceptance result: one continuing CRM relationship with controlled updates. Count the credits in actual history; additional searches, alerts and retries change the total.
For Google Forms intake with budget-based Slack routing, the related Lead Router template is an optional starting point. It routes by budget, not by rotation between reps. Follow the full conflict guide before adapting its mappings. If you need a Make account for a disposable test, use Make.
Further reading
- Full guide: A HubSpot 409 Is a Record-Matching Problem
- Related template: lead router
Top comments (1)
Treating the conflict as evidence about identity is exactly the right frame — a retry re-asks the same wrong question louder. The race you flag near the end deserves emphasis too: search-then-create is not atomic, so two deliveries seconds apart can both see 'no match' and collide anyway. The durable fix is a unique constraint on the normalized key at the storage layer, with the workflow just handling the conflict that constraint surfaces.