Skip to content

Comments

fix: catch HttpError in getRoutedUrl#23844

Merged
ThyMinimalDev merged 4 commits intomainfrom
catch-http-error-in-get-routed-url
Sep 15, 2025
Merged

fix: catch HttpError in getRoutedUrl#23844
ThyMinimalDev merged 4 commits intomainfrom
catch-http-error-in-get-routed-url

Conversation

@ThyMinimalDev
Copy link
Contributor

@ThyMinimalDev ThyMinimalDev commented Sep 15, 2025

What does this PR do?

The change updates error handling in packages/features/routing-forms/lib/getRoutedUrl.ts by replacing TRPCError with HttpError. Two catch blocks now check for e instanceof HttpError and, when matched, return page props containing errorMessage set to e.message. Existing logging and rethrow behavior remain unchanged. Control flow is otherwise unaffected. There are no modifications to exported or public declarations. Minor whitespace adjustments were made.

Visual Demo (For contributors especially)

A visual demonstration is strongly recommended, for both the original and new change (video / image - any one).

Video Demo (if applicable):

  • Show screen recordings of the issue or feature.
  • Demonstrate how to reproduce the issue, the behavior before and after the change.

Image Demo (if applicable):

  • Add side-by-side screenshots of the original and updated change.
  • Highlight any significant change(s).

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • n/a I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 15, 2025

Walkthrough

Imports in packages/features/routing-forms/lib/getRoutedUrl.ts were changed to remove TRPCError and add HttpError. Catch blocks were updated to recognize HttpError or TRPCError (e instanceof HttpError || e instanceof TRPCError) and, when matched, return pageProps containing errorMessage: e.message. Logging and rethrow behavior remain unchanged, control flow is otherwise unaffected, no exported/public declarations were modified, and only minor whitespace adjustments were made.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix: catch HttpError in getRoutedUrl" is concise and directly matches the primary change in the diff (updating error handling in getRoutedUrl to catch HttpError), naming the affected file and clearly conveying the intent to reviewers.
Description Check ✅ Passed The PR description is on-topic and describes the change to error handling in getRoutedUrl, notes there are no exported API changes, and includes requested demos and a task checklist, so it meaningfully relates to the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch catch-http-error-in-get-routed-url

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2400435 and 578915f.

📒 Files selected for processing (1)
  • packages/features/routing-forms/lib/getRoutedUrl.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/features/routing-forms/lib/getRoutedUrl.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@graphite-app graphite-app bot requested a review from a team September 15, 2025 12:42
@keithwillcode keithwillcode added core area: core, team members only foundation platform Anything related to our platform plan labels Sep 15, 2025
@graphite-app graphite-app bot requested a review from a team September 15, 2025 12:42
@dosubot dosubot bot added the 🐛 bug Something isn't working label Sep 15, 2025
crmContactOwnerRecordType = result.crmContactOwnerRecordType;
crmAppSlug = result.crmAppSlug;
} catch (e) {
if (e instanceof TRPCError) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@hbjORbj linked to the changed made in #23768

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

@hariombalhara hariombalhara Sep 15, 2025

Choose a reason for hiding this comment

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

I think it might be safer to keep both, considering that if some fn somewhere starts throwing TRPCError or maybe throwing it currently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

supalarry
supalarry previously approved these changes Sep 15, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/features/routing-forms/lib/getRoutedUrl.ts (2)

174-183: Back-compat and resilience: also handle legacy TRPCError shape and keep original error context

Catching only HttpError risks regressions during migration if upstream still throws TRPCError, and wrapping the error loses stack/context.

Apply:

-  } catch (e) {
-    if (e instanceof HttpError) {
+  } catch (e: unknown) {
+    const isLegacyTRPC = typeof e === "object" && e !== null && (e as any).name === "TRPCError";
+    if (e instanceof HttpError || isLegacyTRPC) {
+      const msg = (e as any)?.message ?? "Request failed";
       return {
         props: {
           ...pageProps,
           form: serializableForm,
           message: null,
-          errorMessage: e.message,
+          errorMessage: msg,
         },
       };
     }
-  
-    log.error("Error handling the response", safeStringify(e));
-    throw new Error("Error handling the response");
+
+    log.error("Error handling the response", safeStringify(e));
+    throw e as Error;
   }

180-181: Confirm user-facing safety of error messages

errorMessage: e.message is rendered to users. Ensure all HttpError messages are pre-sanitized and contain no sensitive internals for routing forms.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fcfb8cc and 2400435.

📒 Files selected for processing (1)
  • packages/features/routing-forms/lib/getRoutedUrl.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/routing-forms/lib/getRoutedUrl.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/routing-forms/lib/getRoutedUrl.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/routing-forms/lib/getRoutedUrl.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).
🧬 Code graph analysis (1)
packages/features/routing-forms/lib/getRoutedUrl.ts (1)
packages/platform/libraries/index.ts (1)
  • HttpError (59-59)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache

import { TRPCError } from "@trpc/server";

import { getUrlSearchParamsToForward } from "./getUrlSearchParamsToForward";
import { HttpError } from "@calcom/lib/http-error";
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Ensure instanceof works: unify HttpError source across throw/catch sites

If upstream throws a different HttpError constructor (e.g., via a platform re‑export) than the one imported here, instanceof HttpError won’t match and the catch path won’t run. Verify that all throwers and checkers import the same symbol from the same module.

Run to confirm a single canonical import path and where HttpError is thrown:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Unique import paths for HttpError:"
rg -nPo --type=ts 'import\s+{?\s*HttpError\s*}?\s+from\s+"[^"]+"' -g '!**/node_modules/**' \
  | sed -E 's/.*from "([^"]+)".*/\1/' | sort -u

echo -e "\nSites throwing HttpError:"
rg -nP --type=ts '\bthrow\s+new\s+HttpError\s*\(' -g '!**/node_modules/**' -C2

echo -e "\nAll instanceof HttpError checks:"
rg -nP --type=ts 'instanceof\s+HttpError' -g '!**/node_modules/**' -C2

Length of output: 183


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Working dir: $(pwd)"
echo -e "\nQuick repo top-level listing:"
ls -la | sed -n '1,80p' || true

echo -e "\nUnique import paths for HttpError (searching all files, disabling ignore heuristics):"
rg -nP -uu -g '!**/node_modules/**' 'import\s+{?\s*HttpError\s*}?\s+from\s+["'\"'\'']?[^"'\''"]+["'\"'\'']' -o -S \
  | sed -E 's/.*from ["'"'"']([^"'"'"']+)["'"'"'].*/\1/' | sort -u || true

echo -e "\nSites throwing HttpError:"
rg -nP -uu -g '!**/node_modules/**' '\bthrow\s+new\s+HttpError\s*\(' -n -S -C2 || true

echo -e "\nAll instanceof HttpError checks:"
rg -nP -uu -g '!**/node_modules/**' 'instanceof\s+HttpError' -n -S -C2 || true

echo -e "\nDefinitions / re-exports of HttpError (class, export, type, interface):"
rg -nP -uu -g '!**/node_modules/**' '(class\s+HttpError|export\s+.*HttpError|type\s+HttpError|interface\s+HttpError|export\s*\{\s*HttpError\s*\})' -n -S -C2 || true

Length of output: 4764


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Working dir: $(pwd)"

echo -e "\nAll occurrences of 'HttpError' (excluding node_modules):"
rg -n --hidden -uu -g '!**/node_modules/**' 'HttpError' -S || true

echo -e "\nImport statements referencing HttpError (showing surrounding 1 line):"
rg -n --hidden -uu -g '!**/node_modules/**' 'HttpError' -S -n -C1 | rg -n --hidden -v '^\s*$' || true

echo -e "\nSites throwing HttpError:"
rg -n --hidden -uu -g '!**/node_modules/**' 'throw\s+new\s+HttpError' -P -S || true

echo -e "\nInstanceof checks:"
rg -n --hidden -uu -g '!**/node_modules/**' 'instanceof\s+HttpError' -P -S || true

echo -e "\nDefinition / export sites (class/export/type/interface mentioning HttpError):"
rg -n --hidden -uu -g '!**/node_modules/**' -e 'class HttpError' -e 'interface HttpError' -e 'type HttpError' -e 'export.*HttpError' -S || true

Length of output: 1031


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Working dir: $(pwd)"

echo -e "\nShow packages/features/routing-forms/lib/getRoutedUrl.ts (if present):"
if [ -f "packages/features/routing-forms/lib/getRoutedUrl.ts" ]; then
  sed -n '1,240p' packages/features/routing-forms/lib/getRoutedUrl.ts || true
else
  echo "file not found: packages/features/routing-forms/lib/getRoutedUrl.ts"
fi

echo -e "\nSearching repository (excluding node_modules and .git) for 'HttpError' occurrences:"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -nI --color=never -e 'HttpError' || true

echo -e "\nUnique files containing HttpError:"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -lI -e 'HttpError' | sort -u || true

echo -e "\nImport lines referencing HttpError:"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -nI --color=never -E "import .*HttpError" || true

echo -e "\nOccurrences of 'throw new HttpError':"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -nI --color=never -E "throw\s+new\s+HttpError" || true

echo -e "\nOccurrences of 'instanceof HttpError':"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -nI --color=never -E "instanceof\s+HttpError" || true

echo -e "\nDefinitions or re-exports mentioning HttpError (class/type/interface/export):"
find . -type f -not -path './node_modules/*' -not -path './.git/*' -print0 \
  | xargs -0 grep -nI --color=never -E "class\s+HttpError|interface\s+HttpError|type\s+HttpError|export\s*\{[^}]*HttpError|export\s+.*HttpError" || true

echo -e "\nSearch node_modules/@calcom (if present) for HttpError references:"
if [ -d "node_modules/@calcom" ]; then
  grep -nI --color=never -R "HttpError" node_modules/@calcom || true
else
  echo "node_modules/@calcom not present"
fi

Length of output: 198468


Ensure instanceof works: unify HttpError source across throw/catch sites

Repository contains two distinct HttpError classes (packages/lib/http-error.ts and apps/web/lib/core/http/error/http-error.ts). packages/features/routing-forms/lib/getRoutedUrl.ts imports "@calcom/lib/http-error" (import at line 29) and uses if (e instanceof HttpError) (line 174) — that check will fail if a different HttpError constructor is thrown. Action: pick a single canonical HttpError (prefer @calcom/lib/http-error / packages/lib/http-error.ts), update all imports to that module (including app-local imports like @lib/core/http/error), or replace instanceof with a shared type guard (e.g., isHttpError(error)) and/or a stable property check.

🤖 Prompt for AI Agents
In packages/features/routing-forms/lib/getRoutedUrl.ts (import at line 29,
instanceof use at line 174): the repo has two distinct HttpError classes so `e
instanceof HttpError` can fail; pick a single canonical HttpError (prefer
packages/lib/http-error.ts exported as @calcom/lib/http-error) and update all
imports across the codebase (including app-local @lib/core/http/error) to import
that canonical module, OR implement and import a shared type guard (e.g.,
isHttpError(error) that checks a stable property like error.status or
error.code) and replace `instanceof HttpError` with that guard to ensure
consistent detection of HttpError instances.

crmAppSlug = result.crmAppSlug;
} catch (e) {
if (e instanceof TRPCError) {
if (e instanceof HttpError) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (e instanceof HttpError) {
if (e instanceof HttpError || e instanceof TRPCError) {

@vercel
Copy link

vercel bot commented Sep 15, 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 Sep 15, 2025 2:11pm
cal-eu Ignored Ignored Sep 15, 2025 2:11pm

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.

LGTM !!

@ThyMinimalDev ThyMinimalDev enabled auto-merge (squash) September 15, 2025 13:32
@github-actions
Copy link
Contributor

github-actions bot commented Sep 15, 2025

E2E results are ready!

@ThyMinimalDev ThyMinimalDev merged commit 3aca339 into main Sep 15, 2025
36 of 37 checks passed
@ThyMinimalDev ThyMinimalDev deleted the catch-http-error-in-get-routed-url branch September 15, 2025 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working core area: core, team members only foundation platform Anything related to our platform plan ready-for-e2e size/XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants