diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index a055aad3f600a4482502da148467bfe622751fe3..5eec97fb4b7b4e5e4f47637b34b0444c1750a334 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -277,6 +277,9 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
 	if (!luafiletransfers)
 		I_Error("No Lua file transfer\n");
 
+	lua_settop(gL, 0); // Just in case...
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	// Retrieve the callback and push it on the stack
 	lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id);
 	lua_gettable(gL, LUA_REGISTRYINDEX);
@@ -304,7 +307,8 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
 	lua_pushstring(gL, luafiletransfers->filename);
 
 	// Call the callback
-	LUA_Call(gL, 2);
+	LUA_Call(gL, 2, 0, 1);
+	lua_settop(gL, 0);
 
 	if (success)
 	{
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index c6b082930385d3edd4762d846532028be1c9ade1..7373401e57910fa298e43788f7cccb1806da826c 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -40,6 +40,10 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
 	// like sending random junk lua commands to crash the server
 
 	if (!gL) goto deny;
+
+	lua_settop(gL, 0); // Just in case...
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
 	if (!lua_istable(gL, -1)) goto deny;
 
@@ -76,7 +80,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
 		READSTRINGN(*cp, buf, 255);
 		lua_pushstring(gL, buf);
 	}
-	LUA_Call(gL, (int)argc); // argc is 1-based, so this will cover the player we passed too.
+	LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too.
 	return;
 
 deny:
@@ -98,6 +102,10 @@ void COM_Lua_f(void)
 	INT32 playernum = consoleplayer;
 
 	I_Assert(gL != NULL);
+
+	lua_settop(gL, 0); // Just in case...
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command
 	I_Assert(lua_istable(gL, -1));
 
@@ -167,7 +175,7 @@ void COM_Lua_f(void)
 	LUA_PushUserdata(gL, &players[playernum], META_PLAYER);
 	for (i = 1; i < COM_Argc(); i++)
 		lua_pushstring(gL, COM_Argv(i));
-	LUA_Call(gL, (int)COM_Argc()); // COM_Argc is 1-based, so this will cover the player we passed too.
+	LUA_Call(gL, (int)COM_Argc(), 0, 1); // COM_Argc is 1-based, so this will cover the player we passed too.
 }
 
 // Wrapper for COM_AddCommand
@@ -277,6 +285,9 @@ static void Lua_OnChange(void)
 
 	/// \todo Network this! XD_LUAVAR
 
+	lua_settop(gL, 0); // Just in case...
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	// From CV_OnChange registry field, get the function for this cvar by name.
 	lua_getfield(gL, LUA_REGISTRYINDEX, "CV_OnChange");
 	I_Assert(lua_istable(gL, -1));
@@ -288,7 +299,7 @@ static void Lua_OnChange(void)
 	lua_getfield(gL, -1, cvname); // get consvar_t* userdata.
 	lua_remove(gL, -2); // pop the CV_Vars table.
 
-	LUA_Call(gL, 1); // call function(cvar)
+	LUA_Call(gL, 1, 0, 1); // call function(cvar)
 	lua_pop(gL, 1); // pop CV_OnChange table
 }
 
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 5db5169d51065f570adde04d81b37f193fbee43c..b079cfe1b9888a31c623210d51cff2a54aa93dd0 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -1345,6 +1345,8 @@ void LUAh_GameHUD(player_t *stplayr)
 	hud_running = true;
 	lua_settop(gL, 0);
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
 	I_Assert(lua_istable(gL, -1));
 	lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs
@@ -1365,7 +1367,7 @@ void LUAh_GameHUD(player_t *stplayr)
 		lua_pushvalue(gL, -5); // graphics library (HUD[1])
 		lua_pushvalue(gL, -5); // stplayr
 		lua_pushvalue(gL, -5); // camera
-		LUA_Call(gL, 3);
+		LUA_Call(gL, 3, 0, 1);
 	}
 	lua_settop(gL, 0);
 	hud_running = false;
@@ -1379,6 +1381,8 @@ void LUAh_ScoresHUD(void)
 	hud_running = true;
 	lua_settop(gL, 0);
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
 	I_Assert(lua_istable(gL, -1));
 	lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs
@@ -1390,7 +1394,7 @@ void LUAh_ScoresHUD(void)
 	lua_pushnil(gL);
 	while (lua_next(gL, -3) != 0) {
 		lua_pushvalue(gL, -3); // graphics library (HUD[1])
-		LUA_Call(gL, 1);
+		LUA_Call(gL, 1, 0, 1);
 	}
 	lua_settop(gL, 0);
 	hud_running = false;
@@ -1404,6 +1408,8 @@ void LUAh_TitleHUD(void)
 	hud_running = true;
 	lua_settop(gL, 0);
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
 	I_Assert(lua_istable(gL, -1));
 	lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs
@@ -1415,7 +1421,7 @@ void LUAh_TitleHUD(void)
 	lua_pushnil(gL);
 	while (lua_next(gL, -3) != 0) {
 		lua_pushvalue(gL, -3); // graphics library (HUD[1])
-		LUA_Call(gL, 1);
+		LUA_Call(gL, 1, 0, 1);
 	}
 	lua_settop(gL, 0);
 	hud_running = false;
@@ -1429,6 +1435,8 @@ void LUAh_TitleCardHUD(player_t *stplayr)
 	hud_running = true;
 	lua_settop(gL, 0);
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
 	I_Assert(lua_istable(gL, -1));
 	lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs
@@ -1448,7 +1456,7 @@ void LUAh_TitleCardHUD(player_t *stplayr)
 		lua_pushvalue(gL, -6); // stplayr
 		lua_pushvalue(gL, -6); // lt_ticker
 		lua_pushvalue(gL, -6); // lt_endtime
-		LUA_Call(gL, 4);
+		LUA_Call(gL, 4, 0, 1);
 	}
 
 	lua_settop(gL, 0);
@@ -1463,6 +1471,8 @@ void LUAh_IntermissionHUD(void)
 	hud_running = true;
 	lua_settop(gL, 0);
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
 	I_Assert(lua_istable(gL, -1));
 	lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs
@@ -1474,7 +1484,7 @@ void LUAh_IntermissionHUD(void)
 	lua_pushnil(gL);
 	while (lua_next(gL, -3) != 0) {
 		lua_pushvalue(gL, -3); // graphics library (HUD[1])
-		LUA_Call(gL, 1);
+		LUA_Call(gL, 1, 0, 1);
 	}
 	lua_settop(gL, 0);
 	hud_running = false;
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index f36cb825b9b04ed7a8bf9ba1527bc464ed395402..566aaa6a0821eeac64fa9b38b5faf2c06b6426fa 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -630,6 +630,9 @@ static void A_Lua(mobj_t *actor)
 	boolean found = false;
 	I_Assert(actor != NULL);
 
+	lua_settop(gL, 0); // Just in case...
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	// get the action for this state
 	lua_getfield(gL, LUA_REGISTRYINDEX, LREG_STATEACTION);
 	I_Assert(lua_istable(gL, -1));
@@ -658,7 +661,7 @@ static void A_Lua(mobj_t *actor)
 	LUA_PushUserdata(gL, actor, META_MOBJ);
 	lua_pushinteger(gL, var1);
 	lua_pushinteger(gL, var2);
-	LUA_Call(gL, 3);
+	LUA_Call(gL, 3, 0, 1);
 
 	if (found)
 	{
@@ -824,6 +827,8 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
 	if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself,
 		return false; // let it call the hardcoded function instead.
 
+	lua_pushcfunction(gL, LUA_GetErrorMessage);
+
 	// grab function by uppercase name.
 	lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
 	{
@@ -836,14 +841,14 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
 
 	if (lua_isnil(gL, -1)) // no match
 	{
-		lua_pop(gL, 1); // pop nil
+		lua_pop(gL, 2); // pop nil and error handler
 		return false; // action not called.
 	}
 
 	if (superstack == MAXRECURSION)
 	{
 		CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
-		lua_pop(gL, 1); // pop function
+		lua_pop(gL, 2); // pop function and error handler
 		return true;
 	}
 
@@ -857,7 +862,8 @@ boolean LUA_CallAction(const char *csaction, mobj_t *actor)
 	superactions[superstack] = csaction;
 	++superstack;
 
-	LUA_Call(gL, 3);
+	LUA_Call(gL, 3, 0, -(2 + 3));
+	lua_pop(gL, -1); // Error handler
 
 	--superstack;
 	superactions[superstack] = NULL;
diff --git a/src/lua_script.c b/src/lua_script.c
index 59e2fe7bed33656eaa73ddf19d1f84b1b0bda04c..be6bf602f5704c0737ffb9e402cbb1823475e476 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -133,6 +133,19 @@ int LUA_GetErrorMessage(lua_State *L)
 	return 1;
 }
 
+int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex)
+{
+	int err = lua_pcall(L, nargs, nresults, errorhandlerindex);
+
+	if (err)
+	{
+		CONS_Alert(CONS_WARNING, "%s\n", lua_tostring(L, -1));
+		lua_pop(L, 1);
+	}
+
+	return err;
+}
+
 // Moved here from lib_getenum.
 int LUA_PushGlobals(lua_State *L, const char *word)
 {
diff --git a/src/lua_script.h b/src/lua_script.h
index 5a3520d11996db85806704f6e88be1d9f8a16f6c..79ba0bb38a5e1aeb6af476fb4c5b01b39aeb63f2 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -40,6 +40,7 @@ void LUA_ClearExtVars(void);
 extern INT32 lua_lumploading; // is LUA_LoadLump being called?
 
 int LUA_GetErrorMessage(lua_State *L);
+int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
 void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
 #ifdef LUA_ALLOW_BYTECODE
 void LUA_DumpFile(const char *filename);
@@ -65,14 +66,6 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc);
 // Console wrapper
 void COM_Lua_f(void);
 
-#define LUA_Call(L,a)\
-{\
-	if (lua_pcall(L, a, 0, 0)) {\
-		CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(L,-1));\
-		lua_pop(L, 1);\
-	}\
-}
-
 #define LUA_ErrInvalid(L, type) luaL_error(L, "accessed " type " doesn't exist anymore, please check 'valid' before using " type ".");
 
 // Deprecation warnings