Skip to content

Conversation

@joeauyeung
Copy link
Contributor

@joeauyeung joeauyeung commented Oct 24, 2025

What does this PR do?

This PR fixes an issue where CRM contact owner fetch failures in routing forms would cause the entire form submission to fail, preventing other important params from being passed to the booking URL.

Problem: When getRoutedUrl calls handleResponse, if the CRM contact owner fetching fails (via routerGetCrmContactOwnerEmail), the entire function throws an error. This means params like formResponseId and teamMembersMatchingAttributeLogic are lost, causing unnecessary refetching when users visit the event URL.

Solution: Wrap the CRM contact owner fetching in a try-catch block. On error, log it and set CRM values to null, allowing the form submission to continue and pass other routing params successfully.

Link to Devin run: https://app.devin.ai/sessions/9eef198322914697a9acb3bba1fa68dc
Requested by: [email protected] (@joeauyeung)

Mandatory Tasks

  • I have self-reviewed the code
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - This is a bug fix that doesn't change public APIs or user-facing behavior.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works. ✅ Existing tests pass (handleResponse.test.ts and getRoutedUrl.test.ts)

How should this be tested?

Environment variables needed:

  • CRM integration credentials (e.g., Salesforce, HubSpot) configured in the routing form
  • NEXT_PUBLIC_WEBAPP_URL set

Test scenario:

  1. Create a routing form with CRM contact owner routing enabled
  2. Configure the form to route to a round-robin event type based on CRM contact owner
  3. Submit the form with an email that either:
    • Doesn't exist in the CRM
    • Causes the CRM API to fail/timeout
    • Has invalid CRM credentials
  4. Expected behavior: Form submission should succeed and redirect to the booking page with formResponseId, teamMembersMatchingAttributeLogic, and other params in the URL, even though CRM routing failed
  5. Verify: Check logs to confirm the error was logged but not thrown

Before this change: Form submission would fail entirely, showing an error page
After this change: Form submission succeeds with null CRM values, passes other routing params

Review Checklist

Critical items to review:

  1. Error handling scope: Is it acceptable to catch all errors during CRM fetching? Should certain error types (auth, validation) be handled differently?
  2. Silent failures: Users won't be notified when CRM routing fails (only logged). Is this acceptable, or should we surface this to users somehow?
  3. Null value behavior: Verify that passing null for crmContactOwnerEmail, crmContactOwnerRecordType, and crmAppSlug correctly prevents refetching and doesn't cause issues downstream in the booking flow
  4. Logging sufficiency: Is the error logging adequate for debugging CRM integration issues, or should we capture additional context?
  5. Test coverage: The existing tests mock handleResponse, so they don't exercise this error path. Should we add a specific test for CRM fetch failures?

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings
  • I have read the contributing guide

Summary by cubic

Form submissions no longer fail when CRM contact owner lookup errors. We catch the error, log it, and continue with null CRM values so other routing params (formResponseId, teamMembersMatchingAttributeLogic) are preserved and passed to the booking URL.

  • Bug Fixes
    • Wrapped routerGetCrmContactOwnerEmail in a try-catch inside handleResponse.
    • On failure, log the error and set CRM fields (email, recordType, appSlug, recordId) to null instead of throwing.
    • Prevent unnecessary refetching by keeping routing params in the booking URL.

When fetching CRM contact owner fails in getRoutedUrl, we now catch
the error and continue with null CRM values instead of throwing. This
ensures that other params (like formResponseId, teamMembersMatchingAttributeLogic)
are still passed to the booking URL, preventing unnecessary refetching
when the user visits the event URL.

Co-Authored-By: [email protected] <[email protected]>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Oct 24, 2025
Added cal.crmFetchAttempted flag that is set when CRM contact owner
fetch is attempted in routing forms. This flag is checked on the
booking page to prevent unnecessary refetching when CRM lookup has
already been attempted (whether it succeeded or failed).

Changes:
- getRoutedUrl: Add cal.crmFetchAttempted=true when fetchCrm is true
- getServerSideProps: Check flag before refetching CRM data
- queries.ts (App Router): Check flag before refetching CRM data
- handleResponse: Catch CRM fetch errors to allow other params to pass

Co-Authored-By: [email protected] <[email protected]>
@pull-request-size pull-request-size bot added size/L and removed size/M labels Oct 24, 2025
@vercel
Copy link

vercel bot commented Oct 24, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Oct 27, 2025 10:11pm
cal-eu Ignored Ignored Oct 27, 2025 10:11pm

@pull-request-size pull-request-size bot added size/M and removed size/L labels Oct 24, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 24, 2025

E2E results are ready!

@joeauyeung joeauyeung marked this pull request as ready for review October 24, 2025 15:56
@graphite-app graphite-app bot requested a review from a team October 24, 2025 15:56
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files


if (!teamMemberEmail || !crmOwnerRecordType || !crmAppSlug) {
const shouldSkipCrmRefetch =
crmFetchAttempted === "true" || (Array.isArray(crmFetchAttempted) && crmFetchAttempted[0] === "true");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we consider crmFetchAttempted as an array ? We should assume it to be a boolean consider "true" to be only truthy value and other values to be false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like for this particular case we shouldn't introduce new query params.

Query params being visible in the URL can be easily tampered with, so we introduce them only when absolutely needed.

How about we use existing query params with special value to mark that CRM fetch was attempted and it failed and thus avoid retrying it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a good approach could be to set crmContactOwnerEmail, crmContactOwnerRecordType, crmAppSlug query params to be set always when fetchCrm is true.

We could set them to empty string when the CRM fetch has failed.

When fetchCRM is false, we could just avoid setting these query parameters at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we seem to be in a place where we could remove fetchCrm argument/flag and consider it as true always.

Copy link
Member

@hariombalhara hariombalhara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a suggestion

@github-actions github-actions bot marked this pull request as draft October 25, 2025 11:30
Address Hariom's feedback to avoid introducing new query params:
- Remove cal.crmFetchAttempted query parameter entirely
- Set CRM params (crmContactOwnerEmail, crmContactOwnerRecordType, crmAppSlug) to empty strings when CRM fetch fails
- Update getCRMData logic to check for param presence instead of truthiness
- Update getUrlSearchParamsToForward to include CRM params when they are not null/undefined (even if empty string)
- Update tests to expect empty strings instead of null values on CRM errors
- Fix eslint warning by changing attributeRoutingConfigParams type from any to string

This approach uses existing query params with special values (empty strings) to signal that CRM fetch was attempted but failed, avoiding the security concerns of adding a new tamperable query param.

Co-Authored-By: [email protected] <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants