diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 91a3bca1600..0135751ce4f 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -311,3 +311,5 @@
// Set on many base types.
#define DEFAULT_APPEARANCE_FLAGS (PIXEL_SCALE)
+///Formats exceptions into a readable string with all the details.
+#define EXCEPTION_TEXT(E) "'[E.name]' ('[E.type]'): '[E.file]':[E.line]:\n'[E.desc]'"
\ No newline at end of file
diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm
index bf708dc5fdd..85f2387558b 100644
--- a/code/_helpers/lists.dm
+++ b/code/_helpers/lists.dm
@@ -797,7 +797,7 @@ var/global/list/json_cache = list()
else if(decoded)
return decoded
catch(var/exception/e)
- log_error("Exception during JSON decoding ([json_to_decode]): [e]")
+ log_error("Exception during JSON decoding ([json_to_decode]): [EXCEPTION_TEXT(e)]")
return list()
/proc/load_text_from_directory(var/directory, var/expected_extension = ".txt", var/recursive = TRUE)
@@ -855,7 +855,7 @@ var/global/list/json_cache = list()
loaded_files[checkfile] = safe_file2text(checkfile)
item_count++
catch(var/exception/e)
- PRINT_STACK_TRACE("Exception loading [checkfile]: [e] on [e.file]:[e.line]")
+ PRINT_STACK_TRACE("Exception loading [checkfile]: [EXCEPTION_TEXT(e)]")
// Return a manifest for further processing.
return list(
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 608a65e36e9..8c47ac8734b 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -254,4 +254,4 @@
error("File not found ([filename])")
catch(var/exception/E)
if(error_on_invalid_return)
- error("Exception when loading file as string: [E]")
+ error("Exception when loading file as string: [EXCEPTION_TEXT(E)]")
diff --git a/code/controllers/subsystems/initialization/secrets.dm b/code/controllers/subsystems/initialization/secrets.dm
index 28244e6a939..fa4d027ade0 100644
--- a/code/controllers/subsystems/initialization/secrets.dm
+++ b/code/controllers/subsystems/initialization/secrets.dm
@@ -272,5 +272,5 @@ SUBSYSTEM_DEF(secrets)
try
file_cache[file_location] = file(file_location)
catch(var/exception/e)
- error("SSsecrets get_file caught exception: [e.name] - [e.file] - [e.line]\n[e.desc]")
+ error("SSsecrets get_file caught exception: [EXCEPTION_TEXT(e)]")
return file_cache[file_location]
diff --git a/code/datums/observation/observation.dm b/code/datums/observation/observation.dm
index efd43bc4f83..892e97ce7c9 100644
--- a/code/datums/observation/observation.dm
+++ b/code/datums/observation/observation.dm
@@ -225,8 +225,7 @@
try
call(listener, proc_call)(arglist(args))
catch (var/exception/e)
- error("[e.name] - [e.file] - [e.line]")
- error(e.desc)
+ error(EXCEPTION_TEXT(e))
unregister_global(listener, proc_call)
// Call the listeners for this specific event source, if they exist.
@@ -240,7 +239,6 @@
try
call(listener, proc_call)(arglist(args))
catch (var/exception/e)
- error("[e.name] - [e.file] - [e.line]")
- error(e.desc)
+ error(EXCEPTION_TEXT(e))
unregister(source, listener, proc_call)
return TRUE
diff --git a/code/modules/admin/verbs/SDQL_2/SDQL_2.dm b/code/modules/admin/verbs/SDQL_2/SDQL_2.dm
index 5eeca1f15dd..852f132be80 100644
--- a/code/modules/admin/verbs/SDQL_2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL_2/SDQL_2.dm
@@ -150,8 +150,7 @@
to_chat(usr, "Query executed on [objs.len] object\s.")
catch(var/exception/e)
to_chat(usr, "An exception has occured during the execution of your query and your query has been aborted.")
- to_chat(usr, "exception name: [e.name]")
- to_chat(usr, "file/line: [e.file]/[e.line]")
+ to_chat(usr, EXCEPTION_TEXT(e))
return
/proc/SDQL_parse(list/query_list)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 685b564b754..ac46b89ff8a 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -119,7 +119,7 @@ var/global/list/time_prefs_fixed = list()
else
SScharacter_setup.queue_load_character(src)
catch(var/exception/E)
- load_failed = "{[stage]} [E]"
+ load_failed = "{[stage]} [EXCEPTION_TEXT(E)]"
throw E
// separated out to avoid stalling SScharacter_setup's Initialize
@@ -127,7 +127,7 @@ var/global/list/time_prefs_fixed = list()
try
load_character()
catch(var/exception/E)
- load_failed = "{lateload_character} [E]"
+ load_failed = "{lateload_character} [EXCEPTION_TEXT(E)]"
throw E
/datum/preferences/proc/migrate_legacy_preferences()
diff --git a/code/unit_tests/del_the_world.dm b/code/unit_tests/del_the_world.dm
index e845561beaa..5b59f304391 100644
--- a/code/unit_tests/del_the_world.dm
+++ b/code/unit_tests/del_the_world.dm
@@ -48,7 +48,7 @@
if(!QDELETED(AM)) // could have returned the qdel hint
qdel(AM, force = TRUE) // must qdel prior to anything it spawns, just in case
catch(var/exception/e)
- failures += "Runtime during creation of [path]: [e.file]:[e.line], [e]\n[e.desc]"
+ failures += "Runtime during creation of [path]: [EXCEPTION_TEXT(e)]"
// If it spawned anything else, delete that.
var/list/del_candidates = spawn_loc.contents - cached_contents
if(length(del_candidates)) // explicit length check is faster here
diff --git a/code/unit_tests/integrated_circuits.dm b/code/unit_tests/integrated_circuits.dm
index 3fb0a800793..ca6d5099487 100644
--- a/code/unit_tests/integrated_circuits.dm
+++ b/code/unit_tests/integrated_circuits.dm
@@ -52,7 +52,7 @@
log_bad("[prefab_type] failed to create or return its item.")
failed_prefabs |= prefab_type
catch(var/exception/e)
- log_bad("[prefab_type] caused an exception: [e] on [e.file]:[e.line]")
+ log_bad("[prefab_type] caused an exception: [EXCEPTION_TEXT(e)]")
failed_prefabs |= prefab_type
if(failed_prefabs.len)
diff --git a/code/unit_tests/items.dm b/code/unit_tests/items.dm
index 5a3ee8bc7c9..2bdf8d336a3 100644
--- a/code/unit_tests/items.dm
+++ b/code/unit_tests/items.dm
@@ -20,7 +20,7 @@
continue
obj_test_instances[path] = I
catch(var/exception/e)
- failures += "Runtime during creation of [path]: [e.file]:[e.line], [e]\n[e.desc]"
+ failures += "Runtime during creation of [path]: [EXCEPTION_TEXT(e)]"
// Create tests + sort by type name so the test can run in alphabetical order
var/list/constant_tests = list()
diff --git a/code/unit_tests/obj_damage_tests.dm b/code/unit_tests/obj_damage_tests.dm
index 744a735a29e..56dc1e07b50 100644
--- a/code/unit_tests/obj_damage_tests.dm
+++ b/code/unit_tests/obj_damage_tests.dm
@@ -96,6 +96,6 @@
I.take_damage(damage_dealt, BRUTE, 0, "TEST", ARMOR_PIERCING_BYPASSED) //Just let the exception handler do its job
. = TRUE
catch(var/exception/E)
- IT.report_failure(src, I.type, "Threw an exception when destroyed by brute damage! '[E]', [E.file]:[E.line].")
+ IT.report_failure(src, I.type, "Threw an exception when destroyed by brute damage!: [EXCEPTION_TEXT(E)]")
. = FALSE
throw E
\ No newline at end of file
diff --git a/code/unit_tests/secrets.dm b/code/unit_tests/secrets.dm
index 0f4ff01cf8b..57cfc98bb54 100644
--- a/code/unit_tests/secrets.dm
+++ b/code/unit_tests/secrets.dm
@@ -23,7 +23,7 @@
try
example = new test_path
catch(var/exception/e)
- fail("Got exception during example secret load/instantiation: [e.name], [e.file]/[e.line]")
+ fail("Got exception during example secret load/instantiation: [EXCEPTION_TEXT(e)]")
if(!istype(example))
fail("Example secret was not created successfully.")
else
diff --git a/mods/mobs/borers/datum/symbiote.dm b/mods/mobs/borers/datum/symbiote.dm
index 48661c27532..a0bc735a5e8 100644
--- a/mods/mobs/borers/datum/symbiote.dm
+++ b/mods/mobs/borers/datum/symbiote.dm
@@ -71,7 +71,7 @@ var/global/list/symbiote_starting_points = list()
host = null
available_hosts = current_hosts
catch(var/exception/e)
- log_debug("Exception during symbiote join: [e]")
+ log_debug("Exception during symbiote join: [EXCEPTION_TEXT(e)]")
if(host)
var/obj/item/organ/external/head = GET_EXTERNAL_ORGAN(host, BP_HEAD)