fix: handle axios errors in Turnstile service to prevent misleading 5…#1601
Conversation
…00 responses Unhandled axios errors from Cloudflare API were propagating as 500 Internal Server Error with confusing message "Request failed with status code 400". Now catches these errors and returns a proper 400 BadRequest with a clear message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This pull request improves error handling in the Turnstile verification service to prevent misleading 500 Internal Server Error responses. Previously, unhandled axios errors from the Cloudflare Turnstile API would propagate as 500 errors with the confusing message "Request failed with status code 400". The changes wrap the axios call in a try-catch block to properly handle these errors and return a more appropriate 400 Bad Request response with a clearer message to users.
Changes:
- Added try-catch block around axios.post call to handle network and API errors
- Implemented logic to distinguish between verification failures (already BadRequestException) and axios errors
- Added error logging to console for debugging purposes
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } catch (error) { | ||
| if (error instanceof BadRequestException) throw error; | ||
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); |
There was a problem hiding this comment.
The catch block doesn't use axios.isAxiosError() to properly type-check the error before accessing axios-specific properties. This pattern is used elsewhere in the codebase (e.g., table-action-activation.service.ts:199) and provides better type safety. Consider checking if the error is an AxiosError before accessing error.response, or handle non-axios errors differently.
| } catch (error) { | |
| if (error instanceof BadRequestException) throw error; | |
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); | |
| } catch (error: unknown) { | |
| if (error instanceof BadRequestException) throw error; | |
| if (axios.isAxiosError(error)) { | |
| console.error('Turnstile verification error:', error.response?.data || error.message); | |
| } else if (error instanceof Error) { | |
| console.error('Turnstile verification error:', error.message); | |
| } else { | |
| console.error('Turnstile verification error:', error); | |
| } |
| } catch (error) { | ||
| if (error instanceof BadRequestException) throw error; | ||
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); | ||
| throw new BadRequestException('Turnstile verification failed. Please try again.'); |
There was a problem hiding this comment.
The error message "Turnstile verification failed. Please try again." on line 46 loses valuable context from the original error. When the Cloudflare API returns a specific error (e.g., network issues, timeout, or API-level failures), this generic message makes debugging difficult. Consider including more specific error information in the log or the user-facing message when appropriate.
| } catch (error) { | |
| if (error instanceof BadRequestException) throw error; | |
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); | |
| throw new BadRequestException('Turnstile verification failed. Please try again.'); | |
| } catch (error: any) { | |
| if (error instanceof BadRequestException) throw error; | |
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); | |
| const baseMessage = 'Turnstile verification failed.'; | |
| let detailedMessage = ''; | |
| if (process.env.NODE_ENV !== 'production') { | |
| const responseData = error?.response?.data; | |
| const errorDetail = | |
| typeof responseData === 'string' | |
| ? responseData | |
| : responseData?.['error-codes']?.join(', ') || error?.message; | |
| if (errorDetail) { | |
| detailedMessage = ` Details: ${errorDetail}`; | |
| } | |
| } | |
| throw new BadRequestException(`${baseMessage}${detailedMessage} Please try again.`); |
| } catch (error) { | ||
| if (error instanceof BadRequestException) throw error; | ||
| console.error('Turnstile verification error:', error?.response?.data || error?.message || error); | ||
| throw new BadRequestException('Turnstile verification failed. Please try again.'); | ||
| } |
There was a problem hiding this comment.
The new error handling logic introduced in the catch block (lines 43-47) lacks test coverage. Given that this repository has comprehensive automated testing using AVA, consider adding tests to verify that: 1) axios errors are properly caught and re-thrown as BadRequestException, 2) the error is logged with appropriate details, and 3) previously thrown BadRequestExceptions are re-thrown correctly without being wrapped.
…00 responses
Unhandled axios errors from Cloudflare API were propagating as 500 Internal Server Error with confusing message "Request failed with status code 400". Now catches these errors and returns a proper 400 BadRequest with a clear message.