@@ -151,6 +151,7 @@ const Initialize = async (): Promise<void> => {
151151 $exception_source : Event . filename ,
152152 $exception_lineno : Event . lineno ,
153153 $exception_colno : Event . colno ,
154+ $exception_origin : "window.onerror" ,
154155 } ,
155156 ) ;
156157 } ) ;
@@ -159,14 +160,79 @@ const Initialize = async (): Promise<void> => {
159160 const Reason = Event . reason ;
160161 if ( ! Reason ) return ;
161162 const Message = String ( Reason . message || Reason ) ;
163+ if ( Message . includes ( "Canceled" ) ) return ;
164+ PH . captureException (
165+ Reason instanceof Error ? Reason : new Error ( Message ) ,
166+ { $exception_origin : "unhandledrejection" } ,
167+ ) ;
168+ } ) ;
169+
170+ // Intercept console.error to capture VS Code internal errors
171+ const OriginalConsoleError = console . error ;
172+ let ConsoleErrorCount = 0 ;
173+ console . error = ( ...Args : unknown [ ] ) => {
174+ OriginalConsoleError . apply ( console , Args ) ;
175+ ConsoleErrorCount ++ ;
176+ const Message = Args . map ( String ) . join ( " " ) . slice ( 0 , 500 ) ;
162177 if (
163178 Message . includes ( "Canceled" ) ||
164- Message . includes ( "FileNotFound " ) ||
165- Message . includes ( "No such file or directory " )
179+ Message . includes ( "[PostHog.js] " ) ||
180+ Message . includes ( "sourceMappingURL " )
166181 )
167182 return ;
168- PH . captureException ( Reason instanceof Error ? Reason : new Error ( Message ) ) ;
169- } ) ;
183+ try {
184+ performance . mark ( `land:console:error` , {
185+ detail : { message : Message , count : ConsoleErrorCount } ,
186+ } ) ;
187+ } catch { }
188+ PH . captureException ( new Error ( Message ) , {
189+ $exception_origin : "console.error" ,
190+ $exception_count : ConsoleErrorCount ,
191+ } ) ;
192+ } ;
193+
194+ // Intercept console.warn for VS Code warnings
195+ const OriginalConsoleWarn = console . warn ;
196+ let ConsoleWarnCount = 0 ;
197+ console . warn = ( ...Args : unknown [ ] ) => {
198+ OriginalConsoleWarn . apply ( console , Args ) ;
199+ ConsoleWarnCount ++ ;
200+ const Message = Args . map ( String ) . join ( " " ) . slice ( 0 , 500 ) ;
201+ try {
202+ performance . mark ( `land:console:warn` , {
203+ detail : { message : Message , count : ConsoleWarnCount } ,
204+ } ) ;
205+ } catch { }
206+ } ;
207+
208+ // Hook into VS Code's error handler if available
209+ const HookVSCodeErrors = ( ) => {
210+ const OnUnexpectedError = ( window as any ) . _VSCODE_onUnexpectedError ;
211+ if ( typeof OnUnexpectedError === "function" ) return ;
212+
213+ // VS Code sets window.onerror and has its own error infrastructure.
214+ // We hook via a global that the workbench checks after bootstrap.
215+ ( window as any ) . _LAND_ERROR_HOOK = ( Error : unknown ) => {
216+ const Message = Error instanceof Error
217+ ? Error . message
218+ : String ( Error ) ;
219+ PH . captureException (
220+ Error instanceof Error ? Error : new Error ( Message ) ,
221+ { $exception_origin : "vscode.onUnexpectedError" } ,
222+ ) ;
223+ try {
224+ performance . mark ( `land:vscode:error` , {
225+ detail : { message : Message . slice ( 0 , 200 ) } ,
226+ } ) ;
227+ } catch { }
228+ } ;
229+ } ;
230+ HookVSCodeErrors ( ) ;
231+
232+ // Capture IPC failures via performance marks
233+ // TauriMainProcessService already emits land:ipc:* marks for all calls.
234+ // Errors are marked as land:ipc:*:error — already captured by the
235+ // PerformanceObserver above.
170236
171237 // Capture boot timing
172238 window . addEventListener ( "load" , ( ) => {
@@ -183,10 +249,36 @@ const Initialize = async (): Promise<void> => {
183249 }
184250 } ) ;
185251
252+ // Capture resource loading errors (failed scripts, stylesheets, images)
253+ window . addEventListener (
254+ "error" ,
255+ ( Event ) => {
256+ const Target = Event . target as HTMLElement ;
257+ if ( Target && Target !== window && "src" in Target ) {
258+ PH . capture ( "land:resource:error" , {
259+ tag : Target . tagName ,
260+ src : ( Target as HTMLScriptElement ) . src ?. slice ( 0 , 200 ) ,
261+ } ) ;
262+ try {
263+ performance . mark ( `land:resource:error` , {
264+ detail : {
265+ tag : Target . tagName ,
266+ src : ( Target as HTMLScriptElement ) . src ?. slice ( 0 , 200 ) ,
267+ } ,
268+ } ) ;
269+ } catch { }
270+ }
271+ } ,
272+ true , // Capture phase — catches resource errors that don't bubble
273+ ) ;
274+
186275 // Flush on page hide
187276 addEventListener ( "visibilitychange" , ( ) => {
188277 if ( document . visibilityState === "hidden" ) {
189- PH . capture ( "land:session:end" ) ;
278+ PH . capture ( "land:session:end" , {
279+ console_errors : ConsoleErrorCount ,
280+ console_warns : ConsoleWarnCount ,
281+ } ) ;
190282 }
191283 } ) ;
192284
0 commit comments