mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-05 10:36:06 -06:00
Compare commits
1 Commits
fix/not-au
...
referencee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dcaaa87d8 |
@@ -2,7 +2,7 @@
|
||||
|
||||
import { z } from "zod";
|
||||
import { ZId } from "@formbricks/types/common";
|
||||
import { AuthorizationError, OperationNotAllowedError } from "@formbricks/types/errors";
|
||||
import { OperationNotAllowedError } from "@formbricks/types/errors";
|
||||
import { ZProjectUpdateInput } from "@formbricks/types/project";
|
||||
import { getMembershipByUserIdOrganizationId } from "@/lib/membership/service";
|
||||
import { getOrganization } from "@/lib/organization/service";
|
||||
@@ -138,7 +138,7 @@ export const getProjectsForSwitcherAction = authenticatedActionClient
|
||||
// Need membership for getProjectsByUserId (1 DB query)
|
||||
const membership = await getMembershipByUserIdOrganizationId(ctx.user.id, parsedInput.organizationId);
|
||||
if (!membership) {
|
||||
throw new AuthorizationError("Membership not found");
|
||||
throw new Error("Membership not found");
|
||||
}
|
||||
|
||||
return await getProjectsByUserId(ctx.user.id, membership);
|
||||
|
||||
@@ -8,12 +8,6 @@ import { type ClientErrorType, getClientErrorData } from "@formbricks/types/erro
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { ErrorComponent } from "@/modules/ui/components/error-component";
|
||||
|
||||
/**
|
||||
* Expected error names that should NOT be reported to Sentry.
|
||||
* These are handled gracefully in the UI (e.g., show "no access" or redirect).
|
||||
*/
|
||||
const EXPECTED_ERROR_NAMES = new Set(["AuthorizationError", "AuthenticationError", "TooManyRequestsError"]);
|
||||
|
||||
/**
|
||||
* Get translated error messages based on error type
|
||||
*/
|
||||
@@ -36,16 +30,10 @@ const ErrorBoundary = ({ error, reset }: { error: Error; reset: () => void }) =>
|
||||
const errorData = getClientErrorData(error);
|
||||
const { title, description } = getErrorMessages(errorData.type, t);
|
||||
|
||||
const isExpectedError = EXPECTED_ERROR_NAMES.has(error.name);
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
console.error(error.message);
|
||||
} else {
|
||||
// Only report unexpected errors to Sentry
|
||||
// Expected errors (auth failures, rate limits) are handled gracefully in the UI
|
||||
if (!isExpectedError) {
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -22,29 +22,24 @@ import { ActionClientCtx } from "./types/context";
|
||||
export const actionClient = createSafeActionClient({
|
||||
handleServerError(e, utils) {
|
||||
const eventId = (utils.ctx as Record<string, any>)?.auditLoggingCtx?.eventId ?? undefined; // keep explicit fallback
|
||||
Sentry.captureException(e, {
|
||||
extra: {
|
||||
eventId,
|
||||
},
|
||||
});
|
||||
|
||||
// Expected errors that should NOT be reported to Sentry
|
||||
// These are handled gracefully in the UI (e.g., show "no access", redirect, or retry message)
|
||||
const isExpectedError =
|
||||
if (
|
||||
e instanceof ResourceNotFoundError ||
|
||||
e instanceof AuthorizationError ||
|
||||
e instanceof InvalidInputError ||
|
||||
e instanceof UnknownError ||
|
||||
e instanceof AuthenticationError ||
|
||||
e instanceof OperationNotAllowedError ||
|
||||
e instanceof TooManyRequestsError;
|
||||
|
||||
if (isExpectedError) {
|
||||
e instanceof TooManyRequestsError
|
||||
) {
|
||||
return e.message;
|
||||
}
|
||||
|
||||
// Only capture unexpected errors to Sentry
|
||||
Sentry.captureException(e, {
|
||||
extra: {
|
||||
eventId,
|
||||
},
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console -- This error needs to be logged for debugging server-side errors
|
||||
logger.withContext({ eventId }).error(e, "SERVER ERROR");
|
||||
return DEFAULT_SERVER_ERROR_MESSAGE;
|
||||
|
||||
@@ -61,7 +61,7 @@ export const getEnvironmentAuth = reactCache(async (environmentId: string): Prom
|
||||
|
||||
const currentUserMembership = await getMembershipByUserIdOrganizationId(session?.user.id, organization.id);
|
||||
if (!currentUserMembership) {
|
||||
throw new AuthorizationError(t("common.membership_not_found"));
|
||||
throw new Error(t("common.membership_not_found"));
|
||||
}
|
||||
|
||||
const { isMember, isOwner, isManager, isBilling } = getAccessFlags(currentUserMembership?.role);
|
||||
@@ -293,7 +293,7 @@ export const getEnvironmentLayoutData = reactCache(
|
||||
|
||||
// Validate user's membership was found
|
||||
if (!membership) {
|
||||
throw new AuthorizationError(t("common.membership_not_found"));
|
||||
throw new Error(t("common.membership_not_found"));
|
||||
}
|
||||
|
||||
// Fetch remaining data in parallel
|
||||
|
||||
@@ -56,9 +56,25 @@ export const CustomScriptsInjector = ({
|
||||
newScript.setAttribute(attr.name, attr.value);
|
||||
});
|
||||
|
||||
// Copy inline script content
|
||||
// Copy inline script content with error handling
|
||||
if (script.textContent) {
|
||||
newScript.textContent = script.textContent;
|
||||
// Wrap inline scripts in try-catch to prevent user script errors from breaking the survey
|
||||
newScript.textContent = `
|
||||
(function() {
|
||||
try {
|
||||
${script.textContent}
|
||||
} catch (error) {
|
||||
console.warn('[Formbricks] Error in custom script:', error);
|
||||
}
|
||||
})();
|
||||
`.trim();
|
||||
}
|
||||
|
||||
// Add error handler for external scripts
|
||||
if (script.src) {
|
||||
newScript.onerror = (error) => {
|
||||
console.warn("[Formbricks] Error loading external script:", script.src, error);
|
||||
};
|
||||
}
|
||||
|
||||
document.head.appendChild(newScript);
|
||||
|
||||
Reference in New Issue
Block a user