Compare commits

...

3 Commits

Author SHA1 Message Date
Bently
8f8bcff2f4 Merge branch 'dev' into add-debugging-to-turnstile 2025-10-27 14:55:00 +00:00
Bentlybro
7b938e918c prettier 2025-10-17 14:17:14 +01:00
Bentlybro
38299877c2 Improve Turnstile error handling and logging
Enhanced the Turnstile component to map Cloudflare error codes to user-friendly messages and pass error codes to the error callback. Added Sentry integration and detailed error logging in useTurnstile for better observability and debugging of Turnstile widget errors.
2025-10-17 11:29:12 +01:00
2 changed files with 54 additions and 4 deletions

View File

@@ -113,13 +113,39 @@ export function Turnstile({
widgetIdRef.current = window.turnstile.render(containerRef.current, {
sitekey: siteKey,
callback: (token: string) => {
console.log("[Turnstile] Verification successful");
onVerify(token);
},
"expired-callback": () => {
console.warn("[Turnstile] Token expired");
onExpire?.();
},
"error-callback": () => {
onError?.(new Error("Turnstile widget encountered an error"));
"error-callback": (errorCode: string) => {
// Capture the actual Cloudflare error code for debugging
console.error("[Turnstile] Error occurred:", errorCode);
// Map Cloudflare error codes to user-friendly messages
const errorMessages: Record<string, string> = {
"110100": "Invalid site configuration. Please contact support.",
"110200": "Domain not allowed for this CAPTCHA.",
"110201": "Hostname mismatch. Please try refreshing the page.",
"110400": "Invalid verification action.",
"110500": "Invalid custom data.",
"110600": "JavaScript execution error.",
"300010": "Session timeout. Please try again.",
"300020": "Network error. Please check your connection.",
"300030": "Challenge closed by user.",
"600010": "Verification timeout. Please try again.",
"600020": "Internal error. Please try again later.",
};
const errorMessage =
errorMessages[errorCode] ||
`Verification failed (Error: ${errorCode}). Please try again.`;
const error = new Error(errorMessage);
(error as any).errorCode = errorCode;
onError?.(error);
},
action,
});
@@ -181,12 +207,13 @@ declare global {
sitekey: string;
callback: (token: string) => void;
"expired-callback"?: () => void;
"error-callback"?: () => void;
"error-callback"?: (errorCode: string) => void;
action?: string;
},
) => string;
reset: (widgetId: string) => void;
remove: (widgetId: string) => void;
getResponse: (widgetId: string) => string | undefined;
};
}
}

View File

@@ -1,4 +1,5 @@
import { useState, useCallback, useEffect } from "react";
import * as Sentry from "@sentry/nextjs";
import { verifyTurnstileToken } from "@/lib/turnstile";
import { environment } from "@/services/environment";
@@ -156,6 +157,28 @@ export function useTurnstile({
(err: Error) => {
if (shouldRender) {
setError(err);
// Log to Sentry with error code if available
const errorCode = (err as any).errorCode;
Sentry.captureException(err, {
level: "error",
extra: {
errorCode,
action,
context: "Turnstile widget error",
message: err.message,
},
tags: {
turnstile_error: errorCode || "unknown",
},
});
console.error("[useTurnstile] Turnstile error:", {
message: err.message,
errorCode,
action,
});
if (resetOnError) {
setToken(null);
setVerified(false);
@@ -163,7 +186,7 @@ export function useTurnstile({
if (onError) onError(err);
}
},
[onError, shouldRender, resetOnError],
[onError, shouldRender, resetOnError, action],
);
return {