We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Error handler should not capture exceptions in DEBUG mode
## Description
Based on the [conclusion from the discussion](https://github.com/centerofci/mathesar/discussions/1150).

Improve backend's debugability via two changes:
1. when backend is in debug-mode, add a pretty-printed stacktrace alongside the current error JSON;
2. stop wrapping unhandled exceptions in 4999 errors.

For some context, we're catching backend exceptions and wrapping them in custom errors so as to provide a uniform error interface to API clients. As it is now it has detrimental effects on debugging, because the resulting error messages don't include stacktraces. Above changes aim to address that.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mathesar/exception_handlers.py`
Content:
```
1 import warnings
2 
3 from django.conf import settings
4 from django.db import IntegrityError as DjangoIntegrityError
5 from django.utils.encoding import force_str
6 from rest_framework.views import exception_handler
7 from rest_framework_friendly_errors.settings import FRIENDLY_EXCEPTION_DICT
8 from sqlalchemy.exc import IntegrityError, ProgrammingError
9 
10 from db.types.exceptions import UnsupportedTypeException
11 from mathesar.api.exceptions.database_exceptions import (
12     base_exceptions as base_api_exceptions,
13     exceptions as database_api_exceptions,
14 )
15 from mathesar.api.exceptions.data_import_exceptions import exceptions as data_import_api_exceptions
16 from mathesar.api.exceptions.error_codes import ErrorCodes
17 from mathesar.api.exceptions.exception_mappers import integrity_error_mapper
18 from mathesar.api.exceptions.generic_exceptions.base_exceptions import get_default_api_exception
19 from mathesar.errors import URLDownloadError, URLNotReachable, URLInvalidContentTypeError
20 
21 exception_map = {
22     IntegrityError: integrity_error_mapper,
23     DjangoIntegrityError: integrity_error_mapper,
24     UnsupportedTypeException: lambda exc: database_api_exceptions.UnsupportedTypeAPIException(exc),
25     ProgrammingError: lambda exc: base_api_exceptions.ProgrammingAPIException(exc),
26     URLDownloadError: lambda exc: data_import_api_exceptions.URLDownloadErrorAPIException(exc),
27     URLNotReachable: lambda exc: data_import_api_exceptions.URLNotReachableAPIException(exc),
28     URLInvalidContentTypeError: lambda exc: data_import_api_exceptions.URLInvalidContentTypeAPIException(exc)
29 }
30 
31 
32 def standardize_error_response(data):
33     for index, error in enumerate(data):
34         if 'code' in error:
35             if error['code'] is not None and str(error['code']) != 'None':
36                 data[index]['code'] = int(error['code'])
37             else:
38                 data[index]['code'] = ErrorCodes.UnknownError.value
39         if 'detail' not in error:
40             data[index]['detail'] = error.pop('details', {})
41     return data
42 
43 
44 def mathesar_exception_handler(exc, context):
45     response = exception_handler(exc, context)
46     # DRF default exception handler does not handle non API errors,
47     # So we convert it to proper API response
48     if not response:
49         # Check if we have an equivalent API exception that is able to convert the exception to proper error
50         mapped_exception_class = exception_map.get(exc.__class__)
51         if mapped_exception_class is None:
52             if getattr(settings, 'MATHESAR_CAPTURE_UNHANDLED_EXCEPTION', False):
53                 mapped_exception_class = get_default_api_exception
54             else:
55                 raise exc
56         api_exception = mapped_exception_class(exc)
57         response = exception_handler(api_exception, context)
58 
59     if response is not None:
60         # Check if conforms to the api spec
61         if is_pretty(response.data):
62             # Validation exception converts error_codes from integer to string, we need to convert it back into
63             response.data = standardize_error_response(response.data)
64             return response
65         # Certain error raised by drf automatically don't follow the api error spec,
66         # so we convert those into proper format
67         else:
68             warnings.warn("Error Response does not conform to the api spec. Please handle the exception properly")
69             error_code = FRIENDLY_EXCEPTION_DICT.get(
70                 exc.__class__.__name__, None
71             )
72             if error_code is None and settings.MATHESAR_MODE != "PRODUCTION":
73                 raise Exception("Error Response does not conform to the api spec. Please handle the exception properly")
74 
75             # Errors thrown by drf automatically
76             if isinstance(response.data, dict):
77                 error_message = response.data.pop('detail', '')
78 
79                 response_data = {}
80                 response_data['code'] = error_code
81                 response_data['message'] = error_message
82                 response_data['details'] = {'exception': force_str(exc)}
83                 response.data = [response_data]
84     return response
85 
86 
87 def is_pretty(data):
88     if not isinstance(data, list):
89         return False
90     else:
91         for error_details in data:
92             if (
93                     not isinstance(error_details, dict)
94                     or 'code' not in error_details
95                     or 'message' not in error_details
96             ):
97                 return False
98         return True
99
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mathesar/exception_handlers.py b/mathesar/exception_handlers.py
--- a/mathesar/exception_handlers.py
+++ b/mathesar/exception_handlers.py
@@ -1,4 +1,5 @@
 import warnings
+import traceback
 
 from django.conf import settings
 from django.db import IntegrityError as DjangoIntegrityError
@@ -38,6 +39,9 @@
                 data[index]['code'] = ErrorCodes.UnknownError.value
         if 'detail' not in error:
             data[index]['detail'] = error.pop('details', {})
+            # Adds a Stack-trace of the error for better debugging
+        if settings.MATHESAR_MODE == 'DEVELOPMENT':
+            data[index]['stacktrace'] = reformat_stacktrace(traceback.format_exc())
     return data
 
 
@@ -80,6 +84,9 @@
                 response_data['code'] = error_code
                 response_data['message'] = error_message
                 response_data['details'] = {'exception': force_str(exc)}
+                # Stacktrace should only be returned if MATHESAR_MODE is set to DEVELOPMENT
+                if settings.MATHESAR_MODE == 'DEVELOPMENT':
+                    response_data['stacktrace'] = reformat_stacktrace(traceback.format_exc())
                 response.data = [response_data]
     return response
 
@@ -96,3 +103,8 @@
             ):
                 return False
         return True
+
+
+def reformat_stacktrace(stacktrace):
+    stacktrace_list = stacktrace.splitlines()[1:]
+    return [f'{i + 1}. {line.strip()}' for i, line in enumerate(stacktrace_list)]

{"golden_diff": "diff --git a/mathesar/exception_handlers.py b/mathesar/exception_handlers.py\n--- a/mathesar/exception_handlers.py\n+++ b/mathesar/exception_handlers.py\n@@ -1,4 +1,5 @@\n import warnings\n+import traceback\n \n from django.conf import settings\n from django.db import IntegrityError as DjangoIntegrityError\n@@ -38,6 +39,9 @@\n                 data[index]['code'] = ErrorCodes.UnknownError.value\n         if 'detail' not in error:\n             data[index]['detail'] = error.pop('details', {})\n+            # Adds a Stack-trace of the error for better debugging\n+        if settings.MATHESAR_MODE == 'DEVELOPMENT':\n+            data[index]['stacktrace'] = reformat_stacktrace(traceback.format_exc())\n     return data\n \n \n@@ -80,6 +84,9 @@\n                 response_data['code'] = error_code\n                 response_data['message'] = error_message\n                 response_data['details'] = {'exception': force_str(exc)}\n+                # Stacktrace should only be returned if MATHESAR_MODE is set to DEVELOPMENT\n+                if settings.MATHESAR_MODE == 'DEVELOPMENT':\n+                    response_data['stacktrace'] = reformat_stacktrace(traceback.format_exc())\n                 response.data = [response_data]\n     return response\n \n@@ -96,3 +103,8 @@\n             ):\n                 return False\n         return True\n+\n+\n+def reformat_stacktrace(stacktrace):\n+    stacktrace_list = stacktrace.splitlines()[1:]\n+    return [f'{i + 1}. {line.strip()}' for i, line in enumerate(stacktrace_list)]\n", "issue": "Error handler should not capture exceptions in DEBUG mode\n## Description\r\nBased on the [conclusion from the discussion](https://github.com/centerofci/mathesar/discussions/1150).\r\n\r\nImprove backend's debugability via two changes:\r\n1. when backend is in debug-mode, add a pretty-printed stacktrace alongside the current error JSON;\r\n2. stop wrapping unhandled exceptions in 4999 errors.\r\n\r\nFor some context, we're catching backend exceptions and wrapping them in custom errors so as to provide a uniform error interface to API clients. As it is now it has detrimental effects on debugging, because the resulting error messages don't include stacktraces. Above changes aim to address that.\n", "before_files": [{"content": "import warnings\n\nfrom django.conf import settings\nfrom django.db import IntegrityError as DjangoIntegrityError\nfrom django.utils.encoding import force_str\nfrom rest_framework.views import exception_handler\nfrom rest_framework_friendly_errors.settings import FRIENDLY_EXCEPTION_DICT\nfrom sqlalchemy.exc import IntegrityError, ProgrammingError\n\nfrom db.types.exceptions import UnsupportedTypeException\nfrom mathesar.api.exceptions.database_exceptions import (\n    base_exceptions as base_api_exceptions,\n    exceptions as database_api_exceptions,\n)\nfrom mathesar.api.exceptions.data_import_exceptions import exceptions as data_import_api_exceptions\nfrom mathesar.api.exceptions.error_codes import ErrorCodes\nfrom mathesar.api.exceptions.exception_mappers import integrity_error_mapper\nfrom mathesar.api.exceptions.generic_exceptions.base_exceptions import get_default_api_exception\nfrom mathesar.errors import URLDownloadError, URLNotReachable, URLInvalidContentTypeError\n\nexception_map = {\n    IntegrityError: integrity_error_mapper,\n    DjangoIntegrityError: integrity_error_mapper,\n    UnsupportedTypeException: lambda exc: database_api_exceptions.UnsupportedTypeAPIException(exc),\n    ProgrammingError: lambda exc: base_api_exceptions.ProgrammingAPIException(exc),\n    URLDownloadError: lambda exc: data_import_api_exceptions.URLDownloadErrorAPIException(exc),\n    URLNotReachable: lambda exc: data_import_api_exceptions.URLNotReachableAPIException(exc),\n    URLInvalidContentTypeError: lambda exc: data_import_api_exceptions.URLInvalidContentTypeAPIException(exc)\n}\n\n\ndef standardize_error_response(data):\n    for index, error in enumerate(data):\n        if 'code' in error:\n            if error['code'] is not None and str(error['code']) != 'None':\n                data[index]['code'] = int(error['code'])\n            else:\n                data[index]['code'] = ErrorCodes.UnknownError.value\n        if 'detail' not in error:\n            data[index]['detail'] = error.pop('details', {})\n    return data\n\n\ndef mathesar_exception_handler(exc, context):\n    response = exception_handler(exc, context)\n    # DRF default exception handler does not handle non API errors,\n    # So we convert it to proper API response\n    if not response:\n        # Check if we have an equivalent API exception that is able to convert the exception to proper error\n        mapped_exception_class = exception_map.get(exc.__class__)\n        if mapped_exception_class is None:\n            if getattr(settings, 'MATHESAR_CAPTURE_UNHANDLED_EXCEPTION', False):\n                mapped_exception_class = get_default_api_exception\n            else:\n                raise exc\n        api_exception = mapped_exception_class(exc)\n        response = exception_handler(api_exception, context)\n\n    if response is not None:\n        # Check if conforms to the api spec\n        if is_pretty(response.data):\n            # Validation exception converts error_codes from integer to string, we need to convert it back into\n            response.data = standardize_error_response(response.data)\n            return response\n        # Certain error raised by drf automatically don't follow the api error spec,\n        # so we convert those into proper format\n        else:\n            warnings.warn(\"Error Response does not conform to the api spec. Please handle the exception properly\")\n            error_code = FRIENDLY_EXCEPTION_DICT.get(\n                exc.__class__.__name__, None\n            )\n            if error_code is None and settings.MATHESAR_MODE != \"PRODUCTION\":\n                raise Exception(\"Error Response does not conform to the api spec. Please handle the exception properly\")\n\n            # Errors thrown by drf automatically\n            if isinstance(response.data, dict):\n                error_message = response.data.pop('detail', '')\n\n                response_data = {}\n                response_data['code'] = error_code\n                response_data['message'] = error_message\n                response_data['details'] = {'exception': force_str(exc)}\n                response.data = [response_data]\n    return response\n\n\ndef is_pretty(data):\n    if not isinstance(data, list):\n        return False\n    else:\n        for error_details in data:\n            if (\n                    not isinstance(error_details, dict)\n                    or 'code' not in error_details\n                    or 'message' not in error_details\n            ):\n                return False\n        return True\n", "path": "mathesar/exception_handlers.py"}], "after_files": [{"content": "import warnings\nimport traceback\n\nfrom django.conf import settings\nfrom django.db import IntegrityError as DjangoIntegrityError\nfrom django.utils.encoding import force_str\nfrom rest_framework.views import exception_handler\nfrom rest_framework_friendly_errors.settings import FRIENDLY_EXCEPTION_DICT\nfrom sqlalchemy.exc import IntegrityError, ProgrammingError\n\nfrom db.types.exceptions import UnsupportedTypeException\nfrom mathesar.api.exceptions.database_exceptions import (\n    base_exceptions as base_api_exceptions,\n    exceptions as database_api_exceptions,\n)\nfrom mathesar.api.exceptions.data_import_exceptions import exceptions as data_import_api_exceptions\nfrom mathesar.api.exceptions.error_codes import ErrorCodes\nfrom mathesar.api.exceptions.exception_mappers import integrity_error_mapper\nfrom mathesar.api.exceptions.generic_exceptions.base_exceptions import get_default_api_exception\nfrom mathesar.errors import URLDownloadError, URLNotReachable, URLInvalidContentTypeError\n\nexception_map = {\n    IntegrityError: integrity_error_mapper,\n    DjangoIntegrityError: integrity_error_mapper,\n    UnsupportedTypeException: lambda exc: database_api_exceptions.UnsupportedTypeAPIException(exc),\n    ProgrammingError: lambda exc: base_api_exceptions.ProgrammingAPIException(exc),\n    URLDownloadError: lambda exc: data_import_api_exceptions.URLDownloadErrorAPIException(exc),\n    URLNotReachable: lambda exc: data_import_api_exceptions.URLNotReachableAPIException(exc),\n    URLInvalidContentTypeError: lambda exc: data_import_api_exceptions.URLInvalidContentTypeAPIException(exc)\n}\n\n\ndef standardize_error_response(data):\n    for index, error in enumerate(data):\n        if 'code' in error:\n            if error['code'] is not None and str(error['code']) != 'None':\n                data[index]['code'] = int(error['code'])\n            else:\n                data[index]['code'] = ErrorCodes.UnknownError.value\n        if 'detail' not in error:\n            data[index]['detail'] = error.pop('details', {})\n            # Adds a Stack-trace of the error for better debugging\n        if settings.MATHESAR_MODE == 'DEVELOPMENT':\n            data[index]['stacktrace'] = reformat_stacktrace(traceback.format_exc())\n    return data\n\n\ndef mathesar_exception_handler(exc, context):\n    response = exception_handler(exc, context)\n    # DRF default exception handler does not handle non API errors,\n    # So we convert it to proper API response\n    if not response:\n        # Check if we have an equivalent API exception that is able to convert the exception to proper error\n        mapped_exception_class = exception_map.get(exc.__class__)\n        if mapped_exception_class is None:\n            if getattr(settings, 'MATHESAR_CAPTURE_UNHANDLED_EXCEPTION', False):\n                mapped_exception_class = get_default_api_exception\n            else:\n                raise exc\n        api_exception = mapped_exception_class(exc)\n        response = exception_handler(api_exception, context)\n\n    if response is not None:\n        # Check if conforms to the api spec\n        if is_pretty(response.data):\n            # Validation exception converts error_codes from integer to string, we need to convert it back into\n            response.data = standardize_error_response(response.data)\n            return response\n        # Certain error raised by drf automatically don't follow the api error spec,\n        # so we convert those into proper format\n        else:\n            warnings.warn(\"Error Response does not conform to the api spec. Please handle the exception properly\")\n            error_code = FRIENDLY_EXCEPTION_DICT.get(\n                exc.__class__.__name__, None\n            )\n            if error_code is None and settings.MATHESAR_MODE != \"PRODUCTION\":\n                raise Exception(\"Error Response does not conform to the api spec. Please handle the exception properly\")\n\n            # Errors thrown by drf automatically\n            if isinstance(response.data, dict):\n                error_message = response.data.pop('detail', '')\n\n                response_data = {}\n                response_data['code'] = error_code\n                response_data['message'] = error_message\n                response_data['details'] = {'exception': force_str(exc)}\n                # Stacktrace should only be returned if MATHESAR_MODE is set to DEVELOPMENT\n                if settings.MATHESAR_MODE == 'DEVELOPMENT':\n                    response_data['stacktrace'] = reformat_stacktrace(traceback.format_exc())\n                response.data = [response_data]\n    return response\n\n\ndef is_pretty(data):\n    if not isinstance(data, list):\n        return False\n    else:\n        for error_details in data:\n            if (\n                    not isinstance(error_details, dict)\n                    or 'code' not in error_details\n                    or 'message' not in error_details\n            ):\n                return False\n        return True\n\n\ndef reformat_stacktrace(stacktrace):\n    stacktrace_list = stacktrace.splitlines()[1:]\n    return [f'{i + 1}. {line.strip()}' for i, line in enumerate(stacktrace_list)]\n", "path": "mathesar/exception_handlers.py"}]}