@@ -77,14 +77,19 @@ export const getTurnstileToken = async (opts: CaptchaOptions) => {
7777 const { modalContainerQuerySelector, modalWrapperQuerySelector, closeModal, openModal } = opts ;
7878 const captcha : Turnstile . Turnstile = await loadCaptcha ( nonce ) ;
7979
80- // Timing and error tracking for diagnostics
81- const startTime = Date . now ( ) ;
82- const errorTimeline : Array < { code : string | number ; t : number } > = [ ] ;
83- // Unique ID to correlate log entries for this captcha attempt
84- const captchaAttemptId =
85- typeof crypto !== 'undefined' && typeof crypto . randomUUID === 'function'
86- ? crypto . randomUUID ( )
87- : Math . random ( ) . toString ( 36 ) . substring ( 2 , 9 ) ;
80+ // Diagnostic tracking - wrapped in try-catch to never affect production behavior
81+ let startTime = 0 ;
82+ let errorTimeline : Array < { code : string | number ; t : number } > = [ ] ;
83+ let captchaAttemptId = '' ;
84+ try {
85+ startTime = Date . now ( ) ;
86+ captchaAttemptId =
87+ typeof crypto !== 'undefined' && typeof crypto . randomUUID === 'function'
88+ ? crypto . randomUUID ( )
89+ : Math . random ( ) . toString ( 36 ) . substring ( 2 , 9 ) ;
90+ } catch {
91+ // Silently ignore - diagnostics should never break captcha flow
92+ }
8893
8994 let captchaToken = '' ;
9095 let id = '' ;
@@ -190,7 +195,11 @@ export const getTurnstileToken = async (opts: CaptchaOptions) => {
190195 }
191196 } ,
192197 'error-callback' : function ( errorCode ) {
193- errorTimeline . push ( { code : errorCode , t : Date . now ( ) - startTime } ) ;
198+ try {
199+ errorTimeline . push ( { code : errorCode , t : Date . now ( ) - startTime } ) ;
200+ } catch {
201+ // Silently ignore - diagnostics should never break captcha flow
202+ }
194203 /**
195204 * By setting retry to 'never' the responsibility for implementing retrying is ours
196205 * https://developers.cloudflare.com/turnstile/reference/client-side-errors/#retrying
@@ -230,22 +239,25 @@ export const getTurnstileToken = async (opts: CaptchaOptions) => {
230239 captcha . remove ( id ) ;
231240 }
232241
233- // Check if widget container exists at failure time (helps diagnose 200100 race conditions)
234- const containerExistsAtFailure = widgetContainerQuerySelector
235- ? ! ! document . querySelector ( widgetContainerQuerySelector )
236- : false ;
242+ // Log failure with full error history for debugging - wrapped to never affect production
243+ try {
244+ const containerExistsAtFailure = widgetContainerQuerySelector
245+ ? ! ! document . querySelector ( widgetContainerQuerySelector )
246+ : false ;
237247
238- // Log failure with full error history for debugging
239- debugLogger . error ( 'Turnstile captcha challenge failed' , {
240- captchaAttemptId,
241- errorTimeline,
242- lastErrorCode : errorTimeline . length > 0 ? errorTimeline [ errorTimeline . length - 1 ] . code : null ,
243- finalError : String ( e ) ,
244- retriesAttempted : retries ,
245- widgetType : captchaTypeUsed ,
246- containerExistsAtFailure,
247- totalDurationMs : Date . now ( ) - startTime ,
248- } , 'captcha' ) ;
248+ debugLogger . error ( 'Turnstile captcha challenge failed' , {
249+ captchaAttemptId,
250+ errorTimeline,
251+ lastErrorCode : errorTimeline . length > 0 ? errorTimeline [ errorTimeline . length - 1 ] . code : null ,
252+ finalError : String ( e ) ,
253+ retriesAttempted : retries ,
254+ widgetType : captchaTypeUsed ,
255+ containerExistsAtFailure,
256+ totalDurationMs : Date . now ( ) - startTime ,
257+ } , 'captcha' ) ;
258+ } catch {
259+ // Silently ignore - diagnostics should never break captcha flow
260+ }
249261
250262 // eslint-disable-next-line @typescript-eslint/only-throw-error
251263 throw {
0 commit comments