mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-03 18:19:00 -06:00
Compare commits
2 Commits
cursor/cus
...
fix/6658-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3f5875145 | ||
|
|
8331bd8431 |
@@ -1,50 +0,0 @@
|
||||
# Fix Summary: Custom Script Error Handling (FORMBRICKS-P5)
|
||||
|
||||
## Problem
|
||||
User-provided custom scripts injected via `customHeadScripts` were calling deprecated MetaMask internal APIs (`window.ethereum._handleChainChanged`), causing unhandled TypeErrors that:
|
||||
- Were reported to Sentry as production errors
|
||||
- Could potentially break the survey experience for users
|
||||
- Occurred when the survey page loaded with certain browser extensions (MetaMask)
|
||||
|
||||
## Root Cause
|
||||
The `CustomScriptsInjector` component was correctly injecting user-provided scripts, but had no protection against runtime errors that occurred *after* the scripts were executed. The existing try-catch block only caught errors during the injection process itself, not runtime errors from the injected code.
|
||||
|
||||
## Solution
|
||||
Enhanced error handling in the `CustomScriptsInjector` component to wrap all user-provided scripts in defensive error handling:
|
||||
|
||||
### Changes Made
|
||||
1. **Inline Script Wrapping** (lines 64-72):
|
||||
- All inline script content is now wrapped in try-catch blocks
|
||||
- Runtime errors are caught and logged to console with `[Formbricks]` prefix
|
||||
- Errors don't break the survey or propagate to error tracking
|
||||
|
||||
2. **External Script Error Handling** (lines 75-77):
|
||||
- Added `onerror` event handlers to all external scripts loaded via `src` attribute
|
||||
- Loading errors are logged to console but don't break functionality
|
||||
|
||||
3. **Documentation**:
|
||||
- Updated JSDoc to clearly state that user scripts are error-isolated
|
||||
- Added inline comments explaining the defensive programming approach
|
||||
|
||||
## Benefits
|
||||
- ✅ Prevents third-party script errors from breaking surveys
|
||||
- ✅ Reduces noise in error tracking (Sentry)
|
||||
- ✅ Maintains debuggability via console warnings
|
||||
- ✅ No breaking changes to existing functionality
|
||||
- ✅ Works for both inline and external scripts
|
||||
|
||||
## Testing Considerations
|
||||
- User scripts with errors will execute up to the point of failure, then stop gracefully
|
||||
- Error messages are visible in browser console for debugging by self-hosted admins
|
||||
- Survey functionality remains intact even if custom scripts fail completely
|
||||
|
||||
## Example
|
||||
**Before**: User script calling `window.ethereum._handleChainChanged()` would throw an unhandled TypeError
|
||||
|
||||
**After**: The error is caught, logged to console as a warning, and the survey continues to function normally
|
||||
|
||||
## Files Modified
|
||||
- `apps/web/modules/survey/link/components/custom-scripts-injector.tsx`
|
||||
|
||||
## Commit
|
||||
- `fix: wrap custom scripts in try-catch to prevent runtime errors` (Fixes FORMBRICKS-P5)
|
||||
@@ -81,7 +81,7 @@ export const OrganizationBreadcrumb = ({
|
||||
getOrganizationsForSwitcherAction({ organizationId: currentOrganizationId }).then((result) => {
|
||||
if (result?.data) {
|
||||
// Sort organizations by name
|
||||
const sorted = result.data.toSorted((a, b) => a.name.localeCompare(b.name));
|
||||
const sorted = [...result.data].sort((a, b) => a.name.localeCompare(b.name));
|
||||
setOrganizations(sorted);
|
||||
} else {
|
||||
// Handle server errors or validation errors
|
||||
|
||||
@@ -82,7 +82,7 @@ export const ProjectBreadcrumb = ({
|
||||
getProjectsForSwitcherAction({ organizationId: currentOrganizationId }).then((result) => {
|
||||
if (result?.data) {
|
||||
// Sort projects by name
|
||||
const sorted = result.data.toSorted((a, b) => a.name.localeCompare(b.name));
|
||||
const sorted = [...result.data].sort((a, b) => a.name.localeCompare(b.name));
|
||||
setProjects(sorted);
|
||||
} else {
|
||||
// Handle server errors or validation errors
|
||||
|
||||
@@ -13,9 +13,6 @@ interface CustomScriptsInjectorProps {
|
||||
* Injects custom HTML scripts into the document head for link surveys.
|
||||
* Supports merging project and survey scripts or replacing project scripts with survey scripts.
|
||||
*
|
||||
* User-provided scripts are wrapped in try-catch blocks to prevent runtime errors
|
||||
* (e.g., calls to deprecated browser APIs) from breaking the survey experience.
|
||||
*
|
||||
* @param projectScripts - Scripts configured at the workspace/project level
|
||||
* @param surveyScripts - Scripts configured at the survey level
|
||||
* @param scriptsMode - "add" merges both, "replace" uses only survey scripts
|
||||
@@ -61,21 +58,9 @@ export const CustomScriptsInjector = ({
|
||||
|
||||
// Copy inline script content
|
||||
if (script.textContent) {
|
||||
// Wrap inline scripts in try-catch to prevent user script errors from breaking the survey
|
||||
newScript.textContent = `
|
||||
try {
|
||||
${script.textContent}
|
||||
} catch (error) {
|
||||
console.warn('[Formbricks] Error in custom script:', error);
|
||||
}
|
||||
`;
|
||||
newScript.textContent = script.textContent;
|
||||
}
|
||||
|
||||
// Add error handler for external scripts loaded via src
|
||||
newScript.onerror = (error) => {
|
||||
console.warn("[Formbricks] Error loading external script:", error);
|
||||
};
|
||||
|
||||
document.head.appendChild(newScript);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user