@@ -10,6 +10,16 @@ import { getAppRouter } from '../navigation/appRouter';
1010// Deduplication: avoid showing multiple toasts for simultaneous errors
1111const recentErrors = new Map < string , number > ( ) ;
1212const ERROR_DEDUP_WINDOW_MS = 3000 ;
13+ let pendingErrorBatch : {
14+ count : number ;
15+ message ?: string ;
16+ timer : ReturnType < typeof setTimeout > | null ;
17+ } | null = null ;
18+
19+ function showErrorToast ( message : string ) {
20+ toast . error ( message , { duration : 5000 } ) ;
21+ announce ( message ) ;
22+ }
1323
1424function notifyError ( message : string , key ?: string ) {
1525 const dedupKey = key || message ;
@@ -21,8 +31,25 @@ function notifyError(message: string, key?: string) {
2131 }
2232
2333 recentErrors . set ( dedupKey , now ) ;
24- toast . error ( message , { duration : 5000 } ) ;
25- announce ( message ) ;
34+
35+ if ( pendingErrorBatch ) {
36+ pendingErrorBatch . count += 1 ;
37+ return ;
38+ }
39+
40+ pendingErrorBatch = {
41+ count : 1 ,
42+ message,
43+ timer : setTimeout ( ( ) => {
44+ if ( ! pendingErrorBatch ) {
45+ return ;
46+ }
47+
48+ const summaryMessage = pendingErrorBatch . count > 1 ? 'Multiple errors occurred' : pendingErrorBatch . message || message ;
49+ showErrorToast ( summaryMessage ) ;
50+ pendingErrorBatch = null ;
51+ } , 150 ) ,
52+ } ;
2653
2754 // Clean up old entries
2855 if ( recentErrors . size > 50 ) {
@@ -164,15 +191,16 @@ apiClient.interceptors.response.use(
164191 if ( error . response ?. status === 429 ) {
165192 const retryAfter = error . response ?. headers ?. [ 'retry-after' ] ;
166193 const seconds = parseInt ( String ( retryAfter ) , 10 ) || 30 ;
167- const endpoint = originalRequest ?. url || error . config ?. url ;
194+ const endpoint = originalRequest ?. url || error . config ?. url || 'unknown' ;
168195 const rawLimit = error . response ?. headers ?. [ 'x-ratelimit-limit' ] || error . response ?. headers ?. [ 'X-RateLimit-Limit' ] ;
169196 const limit = rawLimit ? parseInt ( String ( rawLimit ) , 10 ) : undefined ;
170197 useRateLimitStore . getState ( ) . setRateLimited ( seconds , endpoint , limit ) ;
171- notifyError ( `Too many attempts. Please try again in ${ seconds } seconds.` ) ;
198+ notifyError ( `Too many attempts. Please try again in ${ seconds } seconds.` , `429_ ${ endpoint } ` ) ;
172199 } else if ( ! error . response ) {
173200 notifyError ( 'Network error. Please check your connection.' , 'network_error' ) ;
174201 } else if ( error . response ?. status >= 500 ) {
175- notifyError ( 'A server error occurred. Please try again later.' , `5xx_${ error . response . status } ` ) ;
202+ const endpoint = originalRequest ?. url || error . config ?. url || 'unknown' ;
203+ notifyError ( 'A server error occurred. Please try again later.' , `5xx_${ error . response . status } _${ endpoint } ` ) ;
176204 }
177205
178206 return Promise . reject ( parseApiError ( error ) ) ;
0 commit comments