We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
An exception in a completer crashes xonsh
<!--- Provide a general summary of the issue in the Title above -->
<!--- If you have a question along the lines of "How do I do this Bash command in xonsh"
please first look over the Bash to Xonsh translation guide: https://xon.sh/bash_to_xsh.html
If you don't find an answer there, please do open an issue! -->

## xonfig

<details>

```
+------------------+-----------------+
| xonsh            | 0.9.20          |
| Python           | 3.8.5           |
| PLY              | 3.11            |
| have readline    | True            |
| prompt toolkit   | 3.0.7           |
| shell type       | prompt_toolkit  |
| pygments         | 2.7.1           |
| on posix         | True            |
| on linux         | True            |
| distro           | unknown         |
| on darwin        | False           |
| on windows       | False           |
| on cygwin        | False           |
| on msys2         | False           |
| is superuser     | False           |
| default encoding | utf-8           |
| xonsh encoding   | utf-8           |
| encoding errors  | surrogateescape |
+------------------+-----------------+

```

</details>

## Expected Behavior
Falling back to `sh` is much better than completely losing your shell, but it is still disconcerting, especially for a new user first trying to write a completer. I think that when an exception is raised by a completer xonsh should skip over that completer when finding completion results. Possibly xonsh could prompt the user that completer X encountered an error.

I am not a xonsh expert, but based on the traceback I think it would suffice to put a blanket `except` clause here that calls `continue`, possibly after printing some warning to the user about a bad completer and logging the traceback in some way:

https://github.com/xonsh/xonsh/blob/68993e4b3df51c1972098232e327e1510cc86c4c/xonsh/completer.py#L34-L38

## Current Behavior
<!--- Tell us what happens instead of the expected behavior -->
<!--- If part of your bug report is a traceback, please first enter debug mode before triggering the error
To enter debug mode, set the environment variable `XONSH_DEBUG=1` _before_ starting `xonsh`.
On Linux and OSX, an easy way to to do this is to run `env XONSH_DEBUG=1 xonsh` -->

### Traceback (if applicable)

<details>

```
Traceback (most recent call last):
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py", line 24534, in main
    sys.exit(main_xonsh(args))
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py", line 24565, in main_xonsh
    shell.shell.cmdloop()
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/shell.py", line 224, in cmdloop
    line = self.singleline(auto_suggest=auto_suggest)
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/shell.py", line 193, in singleline
    line = self.prompter.prompt(**prompt_args)
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/shortcuts/prompt.py", line 1013, in prompt
    return self.app.run(set_exception_handler=set_exception_handler)
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py", line 814, in run
    return loop.run_until_complete(
  File "/home/user/conda/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py", line 781, in run_async
    return await _run_async2()
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py", line 769, in _run_async2
    await self.cancel_and_wait_for_background_tasks()
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py", line 870, in cancel_and_wait_for_background_tasks
    await task
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/buffer.py", line 1854, in new_coroutine
    await coroutine(*a, **kw)
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/buffer.py", line 1683, in async_completer
    async for completion in self.completer.get_completions_async(
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/completion/base.py", line 269, in get_completions_async
    async for completion in completer.get_completions_async(
  File "/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/completion/base.py", line 196, in get_completions_async
    for item in self.get_completions(document, complete_event):
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/completer.py", line 51, in get_completions
    completions, l = self.completer.complete(
  File "/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py", line 125, in complete
    out = func(prefix, line, begidx, endidx, ctx)
  File "<xonsh-code>", line 2, in bad_completer
Exception
Xonsh encountered an issue during launch
Failback to /bin/sh
```

</details>

## Steps to Reproduce
<!--- Please try to write out a minimal reproducible snippet to trigger the bug, it will help us fix it! -->

Declare a bad completer:

```
def bad_completer(pref, line, *args):
    raise Exception

completer add test bad_completer start
```

Then start typing a command and hit `Tab`. No completion will  happen (that behavior is okay). When you hit enter, `xonsh` will crash and failback to `sh`.

## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `xonsh/completer.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 """A (tab-)completer for xonsh."""
3 import builtins
4 import collections.abc as cabc
5 
6 
7 class Completer(object):
8     """This provides a list of optional completions for the xonsh shell."""
9 
10     def complete(self, prefix, line, begidx, endidx, ctx=None):
11         """Complete the string, given a possible execution context.
12 
13         Parameters
14         ----------
15         prefix : str
16             The string to match
17         line : str
18             The line that prefix appears on.
19         begidx : int
20             The index in line that prefix starts on.
21         endidx : int
22             The index in line that prefix ends on.
23         ctx : Iterable of str (ie dict, set, etc), optional
24             Names in the current execution context.
25 
26         Returns
27         -------
28         rtn : list of str
29             Possible completions of prefix, sorted alphabetically.
30         lprefix : int
31             Length of the prefix to be replaced in the completion.
32         """
33         ctx = ctx or {}
34         for func in builtins.__xonsh__.completers.values():
35             try:
36                 out = func(prefix, line, begidx, endidx, ctx)
37             except StopIteration:
38                 return set(), len(prefix)
39             if isinstance(out, cabc.Sequence):
40                 res, lprefix = out
41             else:
42                 res = out
43                 lprefix = len(prefix)
44             if res is not None and len(res) != 0:
45 
46                 def sortkey(s):
47                     return s.lstrip(''''"''').lower()
48 
49                 return tuple(sorted(res, key=sortkey)), lprefix
50         return set(), lprefix
51
```
--- 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/xonsh/completer.py b/xonsh/completer.py
--- a/xonsh/completer.py
+++ b/xonsh/completer.py
@@ -3,6 +3,8 @@
 import builtins
 import collections.abc as cabc
 
+from xonsh.tools import print_exception
+
 
 class Completer(object):
     """This provides a list of optional completions for the xonsh shell."""
@@ -36,6 +38,13 @@
                 out = func(prefix, line, begidx, endidx, ctx)
             except StopIteration:
                 return set(), len(prefix)
+            except Exception as e:
+                print_exception(
+                    f"Completer {func.__name__} raises exception when get "
+                    f"(prefix={repr(prefix)}, line={repr(line)}, begidx={repr(begidx)}, endidx={repr(endidx)}):\n"
+                    f"{e}"
+                )
+                return set(), len(prefix)
             if isinstance(out, cabc.Sequence):
                 res, lprefix = out
             else:

{"golden_diff": "diff --git a/xonsh/completer.py b/xonsh/completer.py\n--- a/xonsh/completer.py\n+++ b/xonsh/completer.py\n@@ -3,6 +3,8 @@\n import builtins\n import collections.abc as cabc\n \n+from xonsh.tools import print_exception\n+\n \n class Completer(object):\n     \"\"\"This provides a list of optional completions for the xonsh shell.\"\"\"\n@@ -36,6 +38,13 @@\n                 out = func(prefix, line, begidx, endidx, ctx)\n             except StopIteration:\n                 return set(), len(prefix)\n+            except Exception as e:\n+                print_exception(\n+                    f\"Completer {func.__name__} raises exception when get \"\n+                    f\"(prefix={repr(prefix)}, line={repr(line)}, begidx={repr(begidx)}, endidx={repr(endidx)}):\\n\"\n+                    f\"{e}\"\n+                )\n+                return set(), len(prefix)\n             if isinstance(out, cabc.Sequence):\n                 res, lprefix = out\n             else:\n", "issue": "An exception in a completer crashes xonsh\n<!--- Provide a general summary of the issue in the Title above -->\r\n<!--- If you have a question along the lines of \"How do I do this Bash command in xonsh\"\r\nplease first look over the Bash to Xonsh translation guide: https://xon.sh/bash_to_xsh.html\r\nIf you don't find an answer there, please do open an issue! -->\r\n\r\n## xonfig\r\n\r\n<details>\r\n\r\n```\r\n+------------------+-----------------+\r\n| xonsh            | 0.9.20          |\r\n| Python           | 3.8.5           |\r\n| PLY              | 3.11            |\r\n| have readline    | True            |\r\n| prompt toolkit   | 3.0.7           |\r\n| shell type       | prompt_toolkit  |\r\n| pygments         | 2.7.1           |\r\n| on posix         | True            |\r\n| on linux         | True            |\r\n| distro           | unknown         |\r\n| on darwin        | False           |\r\n| on windows       | False           |\r\n| on cygwin        | False           |\r\n| on msys2         | False           |\r\n| is superuser     | False           |\r\n| default encoding | utf-8           |\r\n| xonsh encoding   | utf-8           |\r\n| encoding errors  | surrogateescape |\r\n+------------------+-----------------+\r\n\r\n```\r\n\r\n</details>\r\n\r\n## Expected Behavior\r\nFalling back to `sh` is much better than completely losing your shell, but it is still disconcerting, especially for a new user first trying to write a completer. I think that when an exception is raised by a completer xonsh should skip over that completer when finding completion results. Possibly xonsh could prompt the user that completer X encountered an error.\r\n\r\nI am not a xonsh expert, but based on the traceback I think it would suffice to put a blanket `except` clause here that calls `continue`, possibly after printing some warning to the user about a bad completer and logging the traceback in some way:\r\n\r\nhttps://github.com/xonsh/xonsh/blob/68993e4b3df51c1972098232e327e1510cc86c4c/xonsh/completer.py#L34-L38\r\n\r\n## Current Behavior\r\n<!--- Tell us what happens instead of the expected behavior -->\r\n<!--- If part of your bug report is a traceback, please first enter debug mode before triggering the error\r\nTo enter debug mode, set the environment variable `XONSH_DEBUG=1` _before_ starting `xonsh`.\r\nOn Linux and OSX, an easy way to to do this is to run `env XONSH_DEBUG=1 xonsh` -->\r\n\r\n### Traceback (if applicable)\r\n\r\n<details>\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py\", line 24534, in main\r\n    sys.exit(main_xonsh(args))\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py\", line 24565, in main_xonsh\r\n    shell.shell.cmdloop()\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/shell.py\", line 224, in cmdloop\r\n    line = self.singleline(auto_suggest=auto_suggest)\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/shell.py\", line 193, in singleline\r\n    line = self.prompter.prompt(**prompt_args)\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/shortcuts/prompt.py\", line 1013, in prompt\r\n    return self.app.run(set_exception_handler=set_exception_handler)\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py\", line 814, in run\r\n    return loop.run_until_complete(\r\n  File \"/home/user/conda/lib/python3.8/asyncio/base_events.py\", line 616, in run_until_complete\r\n    return future.result()\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py\", line 781, in run_async\r\n    return await _run_async2()\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py\", line 769, in _run_async2\r\n    await self.cancel_and_wait_for_background_tasks()\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/application/application.py\", line 870, in cancel_and_wait_for_background_tasks\r\n    await task\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/buffer.py\", line 1854, in new_coroutine\r\n    await coroutine(*a, **kw)\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/buffer.py\", line 1683, in async_completer\r\n    async for completion in self.completer.get_completions_async(\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/completion/base.py\", line 269, in get_completions_async\r\n    async for completion in completer.get_completions_async(\r\n  File \"/home/user/conda/lib/python3.8/site-packages/prompt_toolkit/completion/base.py\", line 196, in get_completions_async\r\n    for item in self.get_completions(document, complete_event):\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/ptk_shell/completer.py\", line 51, in get_completions\r\n    completions, l = self.completer.complete(\r\n  File \"/home/user/conda/lib/python3.8/site-packages/xonsh/__amalgam__.py\", line 125, in complete\r\n    out = func(prefix, line, begidx, endidx, ctx)\r\n  File \"<xonsh-code>\", line 2, in bad_completer\r\nException\r\nXonsh encountered an issue during launch\r\nFailback to /bin/sh\r\n```\r\n\r\n</details>\r\n\r\n## Steps to Reproduce\r\n<!--- Please try to write out a minimal reproducible snippet to trigger the bug, it will help us fix it! -->\r\n\r\nDeclare a bad completer:\r\n\r\n```\r\ndef bad_completer(pref, line, *args):\r\n    raise Exception\r\n\r\ncompleter add test bad_completer start\r\n```\r\n\r\nThen start typing a command and hit `Tab`. No completion will  happen (that behavior is okay). When you hit enter, `xonsh` will crash and failback to `sh`.\r\n\r\n## For community\r\n\u2b07\ufe0f  **Please click the \ud83d\udc4d reaction instead of leaving a `+1` or \ud83d\udc4d  comment**\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"A (tab-)completer for xonsh.\"\"\"\nimport builtins\nimport collections.abc as cabc\n\n\nclass Completer(object):\n    \"\"\"This provides a list of optional completions for the xonsh shell.\"\"\"\n\n    def complete(self, prefix, line, begidx, endidx, ctx=None):\n        \"\"\"Complete the string, given a possible execution context.\n\n        Parameters\n        ----------\n        prefix : str\n            The string to match\n        line : str\n            The line that prefix appears on.\n        begidx : int\n            The index in line that prefix starts on.\n        endidx : int\n            The index in line that prefix ends on.\n        ctx : Iterable of str (ie dict, set, etc), optional\n            Names in the current execution context.\n\n        Returns\n        -------\n        rtn : list of str\n            Possible completions of prefix, sorted alphabetically.\n        lprefix : int\n            Length of the prefix to be replaced in the completion.\n        \"\"\"\n        ctx = ctx or {}\n        for func in builtins.__xonsh__.completers.values():\n            try:\n                out = func(prefix, line, begidx, endidx, ctx)\n            except StopIteration:\n                return set(), len(prefix)\n            if isinstance(out, cabc.Sequence):\n                res, lprefix = out\n            else:\n                res = out\n                lprefix = len(prefix)\n            if res is not None and len(res) != 0:\n\n                def sortkey(s):\n                    return s.lstrip(''''\"''').lower()\n\n                return tuple(sorted(res, key=sortkey)), lprefix\n        return set(), lprefix\n", "path": "xonsh/completer.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\"\"\"A (tab-)completer for xonsh.\"\"\"\nimport builtins\nimport collections.abc as cabc\n\nfrom xonsh.tools import print_exception\n\n\nclass Completer(object):\n    \"\"\"This provides a list of optional completions for the xonsh shell.\"\"\"\n\n    def complete(self, prefix, line, begidx, endidx, ctx=None):\n        \"\"\"Complete the string, given a possible execution context.\n\n        Parameters\n        ----------\n        prefix : str\n            The string to match\n        line : str\n            The line that prefix appears on.\n        begidx : int\n            The index in line that prefix starts on.\n        endidx : int\n            The index in line that prefix ends on.\n        ctx : Iterable of str (ie dict, set, etc), optional\n            Names in the current execution context.\n\n        Returns\n        -------\n        rtn : list of str\n            Possible completions of prefix, sorted alphabetically.\n        lprefix : int\n            Length of the prefix to be replaced in the completion.\n        \"\"\"\n        ctx = ctx or {}\n        for func in builtins.__xonsh__.completers.values():\n            try:\n                out = func(prefix, line, begidx, endidx, ctx)\n            except StopIteration:\n                return set(), len(prefix)\n            except Exception as e:\n                print_exception(\n                    f\"Completer {func.__name__} raises exception when get \"\n                    f\"(prefix={repr(prefix)}, line={repr(line)}, begidx={repr(begidx)}, endidx={repr(endidx)}):\\n\"\n                    f\"{e}\"\n                )\n                return set(), len(prefix)\n            if isinstance(out, cabc.Sequence):\n                res, lprefix = out\n            else:\n                res = out\n                lprefix = len(prefix)\n            if res is not None and len(res) != 0:\n\n                def sortkey(s):\n                    return s.lstrip(''''\"''').lower()\n\n                return tuple(sorted(res, key=sortkey)), lprefix\n        return set(), lprefix\n", "path": "xonsh/completer.py"}]}