@@ -2020,33 +2020,10 @@ impl LuaVM {
20202020 /// Set runtime error and return lightweight error enum
20212021 /// If an error handler is set (via xpcall), it will be called immediately
20222022 pub fn error ( & mut self , message : impl Into < String > ) -> LuaError {
2023- let msg = message. into ( ) ;
2024-
2025- // Check if there's an error handler (set by xpcall)
2026- if let Some ( handler) = self . error_handler . clone ( ) {
2027- // Call the error handler with the error message
2028- // Note: The call stack is still intact at this point
2029- let err_value = self . create_string ( & msg) ;
2030-
2031- match self . call_function_internal ( handler, vec ! [ err_value] ) {
2032- Ok ( handler_results) => {
2033- // Error handler succeeded, use its return value as the new error message
2034- if let Some ( result) = handler_results. first ( ) {
2035- self . error_message = self . value_to_string_raw ( result) ;
2036- } else {
2037- self . error_message = msg;
2038- }
2039- }
2040- Err ( _) => {
2041- // Error handler itself failed, use original message
2042- self . error_message = format ! ( "error in error handler: {}" , msg) ;
2043- }
2044- }
2045- } else {
2046- // No error handler, just set the message
2047- self . error_message = msg;
2048- }
2049-
2023+ // Simply set the error message - error handling is done by xpcall
2024+ // when the error propagates back through the Rust call stack.
2025+ // At that point, the Lua call stack is still intact.
2026+ self . error_message = message. into ( ) ;
20502027 LuaError :: RuntimeError
20512028 }
20522029
@@ -2450,33 +2427,44 @@ impl LuaVM {
24502427 args : Vec < LuaValue > ,
24512428 err_handler : LuaValue ,
24522429 ) -> LuaResult < ( bool , Vec < LuaValue > ) > {
2453- // Save old error handler and set the new one
2454- let old_handler = self . error_handler . clone ( ) ;
2455- self . error_handler = Some ( err_handler. clone ( ) ) ;
2456-
24572430 let initial_frame_count = self . frame_count ;
24582431
2459- // Call the function - if it errors, error() will call the handler
2432+ // Call the function
24602433 let result = self . call_function_internal ( func, args) ;
24612434
2462- // Restore old error handler
2463- self . error_handler = old_handler;
2464-
24652435 match result {
24662436 Ok ( values) => Ok ( ( true , values) ) ,
24672437 Err ( LuaError :: Yield ) => Err ( LuaError :: Yield ) ,
24682438 Err ( _) => {
2469- // Error occurred (and handler was already called in error())
2470- // Clean up frames created by the failed function call
2439+ // Error occurred - call the error handler NOW while the stack is still intact
2440+ // This allows debug.traceback() to see the full call stack
2441+ let error_msg = self . error_message . clone ( ) ;
2442+ let err_value = self . create_string ( & error_msg) ;
2443+
2444+ let handled_msg = match self . call_function_internal ( err_handler, vec ! [ err_value] ) {
2445+ Ok ( handler_results) => {
2446+ // Error handler succeeded, use its return value as the error message
2447+ if let Some ( result) = handler_results. first ( ) {
2448+ self . value_to_string_raw ( result)
2449+ } else {
2450+ error_msg
2451+ }
2452+ }
2453+ Err ( _) => {
2454+ // Error handler itself failed
2455+ format ! ( "error in error handling: {}" , error_msg)
2456+ }
2457+ } ;
2458+
2459+ // NOW clean up frames created by the failed function call
24712460 while self . frame_count > initial_frame_count {
24722461 let frame = self . pop_frame ( ) . unwrap ( ) ;
24732462 // Close upvalues belonging to this frame
24742463 self . close_upvalues_from ( frame. base_ptr ) ;
24752464 }
24762465
2477- // Return the error message (which may have been modified by the handler)
2478- let msg = self . error_message . clone ( ) ;
2479- let err_str = self . create_string ( & msg) ;
2466+ // Return the handled error message
2467+ let err_str = self . create_string ( & handled_msg) ;
24802468 Ok ( ( false , vec ! [ err_str] ) )
24812469 }
24822470 }
0 commit comments