We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Crazy error message shown when two widgets have the same key
# Steps to reproduce

1. Run this code
   ```
   import streamlit as st

   st.button("OK")
   st.button("OK")
   ```
2. Observe!

## Expected behavior:

You should get one button plus an error message explaining you can't have to `st.button` calls with the same key.

## Actual behavior:

The error message complains about `st.-3952690150221448179` :scream_cat: 

See screenshot:
![image](https://user-images.githubusercontent.com/690814/91766363-4f35d480-eb8f-11ea-8648-ce832caf4da3.png)

## Is this a regression?

yes

# Debug info

- Streamlit version: 0.65.0


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/streamlit/elements/utils.py`
Content:
```
1 import textwrap
2 
3 from streamlit import type_util
4 from streamlit.report_thread import get_report_ctx
5 from streamlit.errors import DuplicateWidgetID
6 from typing import Optional, Any
7 
8 
9 class NoValue(object):
10     """Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()
11     call to return None. This is needed because `DeltaGenerator._enqueue`
12     replaces `None` with a `DeltaGenerator` (for use in non-widget elements).
13     """
14 
15     pass
16 
17 
18 def _clean_text(text):
19     return textwrap.dedent(str(text)).strip()
20 
21 
22 def _build_duplicate_widget_message(
23     widget_func_name: str, user_key: Optional[str] = None
24 ) -> str:
25     if user_key is not None:
26         message = textwrap.dedent(
27             """
28             There are multiple identical `st.{widget_type}` widgets with
29             `key='{user_key}'`.
30 
31             To fix this, please make sure that the `key` argument is unique for
32             each `st.{widget_type}` you create.
33             """
34         )
35     else:
36         message = textwrap.dedent(
37             """
38             There are multiple identical `st.{widget_type}` widgets with the
39             same generated key.
40 
41             (When a widget is created, it's assigned an internal key based on
42             its structure. Multiple widgets with an identical structure will
43             result in the same internal key, which causes this error.)
44 
45             To fix this, please pass a unique `key` argument to
46             `st.{widget_type}`.
47             """
48         )
49 
50     return message.strip("\n").format(widget_type=widget_func_name, user_key=user_key)
51 
52 
53 def _set_widget_id(
54     element_type: str,
55     element_proto: Any,
56     user_key: Optional[str] = None,
57     widget_func_name: Optional[str] = None,
58 ) -> None:
59     """Set the widget id.
60 
61     Parameters
62     ----------
63     element_type : str
64         The type of the element as stored in proto.
65     element_proto : proto
66         The proto of the specified type (e.g. Button/Multiselect/Slider proto)
67     user_key : str or None
68         Optional user-specified key to use for the widget ID.
69         If this is None, we'll generate an ID by hashing the element.
70     widget_func_name : str or None
71         The widget's DeltaGenerator function name, if it's different from
72         its element_type. Custom components are a special case: they all have
73         the element_type "component_instance", but are instantiated with
74         dynamically-named functions.
75 
76     """
77 
78     if widget_func_name is None:
79         widget_func_name = element_type
80 
81     # Identify the widget with a hash of type + contents
82     element_hash = hash((element_type, element_proto.SerializeToString()))
83     if user_key is not None:
84         widget_id = "%s-%s" % (user_key, element_hash)
85     else:
86         widget_id = "%s" % element_hash
87 
88     ctx = get_report_ctx()
89     if ctx is not None:
90         added = ctx.widget_ids_this_run.add(widget_id)
91         if not added:
92             raise DuplicateWidgetID(
93                 _build_duplicate_widget_message(widget_id, user_key)
94             )
95     element_proto.id = widget_id
96 
97 
98 def _get_widget_ui_value(
99     element_type: str,
100     element_proto: Any,
101     user_key: Optional[str] = None,
102     widget_func_name: Optional[str] = None,
103 ) -> Any:
104     """Get the widget ui_value from the report context.
105     NOTE: This function should be called after the proto has been filled.
106 
107     Parameters
108     ----------
109     element_type : str
110         The type of the element as stored in proto.
111     element : proto
112         The proto of the specified type (e.g. Button/Multiselect/Slider proto)
113     user_key : str
114         Optional user-specified string to use as the widget ID.
115         If this is None, we'll generate an ID by hashing the element.
116     widget_func_name : str or None
117         The widget's DeltaGenerator function name, if it's different from
118         its element_type. Custom components are a special case: they all have
119         the element_type "component_instance", but are instantiated with
120         dynamically-named functions.
121 
122     Returns
123     -------
124     ui_value : any
125         The value of the widget set by the client or
126         the default value passed. If the report context
127         doesn't exist, None will be returned.
128 
129     """
130     _set_widget_id(element_type, element_proto, user_key, widget_func_name)
131     ctx = get_report_ctx()
132     ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None
133     return ui_value
134 
135 
136 def last_index_for_melted_dataframes(data):
137     if type_util.is_dataframe_compatible(data):
138         data = type_util.convert_anything_to_df(data)
139 
140         if data.index.size > 0:
141             return data.index[-1]
142 
143     return None
144
```
--- 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/lib/streamlit/elements/utils.py b/lib/streamlit/elements/utils.py
--- a/lib/streamlit/elements/utils.py
+++ b/lib/streamlit/elements/utils.py
@@ -90,7 +90,7 @@
         added = ctx.widget_ids_this_run.add(widget_id)
         if not added:
             raise DuplicateWidgetID(
-                _build_duplicate_widget_message(widget_id, user_key)
+                _build_duplicate_widget_message(widget_func_name, user_key)
             )
     element_proto.id = widget_id

{"golden_diff": "diff --git a/lib/streamlit/elements/utils.py b/lib/streamlit/elements/utils.py\n--- a/lib/streamlit/elements/utils.py\n+++ b/lib/streamlit/elements/utils.py\n@@ -90,7 +90,7 @@\n         added = ctx.widget_ids_this_run.add(widget_id)\n         if not added:\n             raise DuplicateWidgetID(\n-                _build_duplicate_widget_message(widget_id, user_key)\n+                _build_duplicate_widget_message(widget_func_name, user_key)\n             )\n     element_proto.id = widget_id\n", "issue": "Crazy error message shown when two widgets have the same key\n# Steps to reproduce\r\n\r\n1. Run this code\r\n   ```\r\n   import streamlit as st\r\n\r\n   st.button(\"OK\")\r\n   st.button(\"OK\")\r\n   ```\r\n2. Observe!\r\n\r\n## Expected behavior:\r\n\r\nYou should get one button plus an error message explaining you can't have to `st.button` calls with the same key.\r\n\r\n## Actual behavior:\r\n\r\nThe error message complains about `st.-3952690150221448179` :scream_cat: \r\n\r\nSee screenshot:\r\n![image](https://user-images.githubusercontent.com/690814/91766363-4f35d480-eb8f-11ea-8648-ce832caf4da3.png)\r\n\r\n## Is this a regression?\r\n\r\nyes\r\n\r\n# Debug info\r\n\r\n- Streamlit version: 0.65.0\r\n\n", "before_files": [{"content": "import textwrap\n\nfrom streamlit import type_util\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.errors import DuplicateWidgetID\nfrom typing import Optional, Any\n\n\nclass NoValue(object):\n    \"\"\"Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()\n    call to return None. This is needed because `DeltaGenerator._enqueue`\n    replaces `None` with a `DeltaGenerator` (for use in non-widget elements).\n    \"\"\"\n\n    pass\n\n\ndef _clean_text(text):\n    return textwrap.dedent(str(text)).strip()\n\n\ndef _build_duplicate_widget_message(\n    widget_func_name: str, user_key: Optional[str] = None\n) -> str:\n    if user_key is not None:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with\n            `key='{user_key}'`.\n\n            To fix this, please make sure that the `key` argument is unique for\n            each `st.{widget_type}` you create.\n            \"\"\"\n        )\n    else:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with the\n            same generated key.\n\n            (When a widget is created, it's assigned an internal key based on\n            its structure. Multiple widgets with an identical structure will\n            result in the same internal key, which causes this error.)\n\n            To fix this, please pass a unique `key` argument to\n            `st.{widget_type}`.\n            \"\"\"\n        )\n\n    return message.strip(\"\\n\").format(widget_type=widget_func_name, user_key=user_key)\n\n\ndef _set_widget_id(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> None:\n    \"\"\"Set the widget id.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element_proto : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str or None\n        Optional user-specified key to use for the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    \"\"\"\n\n    if widget_func_name is None:\n        widget_func_name = element_type\n\n    # Identify the widget with a hash of type + contents\n    element_hash = hash((element_type, element_proto.SerializeToString()))\n    if user_key is not None:\n        widget_id = \"%s-%s\" % (user_key, element_hash)\n    else:\n        widget_id = \"%s\" % element_hash\n\n    ctx = get_report_ctx()\n    if ctx is not None:\n        added = ctx.widget_ids_this_run.add(widget_id)\n        if not added:\n            raise DuplicateWidgetID(\n                _build_duplicate_widget_message(widget_id, user_key)\n            )\n    element_proto.id = widget_id\n\n\ndef _get_widget_ui_value(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> Any:\n    \"\"\"Get the widget ui_value from the report context.\n    NOTE: This function should be called after the proto has been filled.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str\n        Optional user-specified string to use as the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    Returns\n    -------\n    ui_value : any\n        The value of the widget set by the client or\n        the default value passed. If the report context\n        doesn't exist, None will be returned.\n\n    \"\"\"\n    _set_widget_id(element_type, element_proto, user_key, widget_func_name)\n    ctx = get_report_ctx()\n    ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None\n    return ui_value\n\n\ndef last_index_for_melted_dataframes(data):\n    if type_util.is_dataframe_compatible(data):\n        data = type_util.convert_anything_to_df(data)\n\n        if data.index.size > 0:\n            return data.index[-1]\n\n    return None\n", "path": "lib/streamlit/elements/utils.py"}], "after_files": [{"content": "import textwrap\n\nfrom streamlit import type_util\nfrom streamlit.report_thread import get_report_ctx\nfrom streamlit.errors import DuplicateWidgetID\nfrom typing import Optional, Any\n\n\nclass NoValue(object):\n    \"\"\"Return this from DeltaGenerator.foo_widget() when you want the st.foo_widget()\n    call to return None. This is needed because `DeltaGenerator._enqueue`\n    replaces `None` with a `DeltaGenerator` (for use in non-widget elements).\n    \"\"\"\n\n    pass\n\n\ndef _clean_text(text):\n    return textwrap.dedent(str(text)).strip()\n\n\ndef _build_duplicate_widget_message(\n    widget_func_name: str, user_key: Optional[str] = None\n) -> str:\n    if user_key is not None:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with\n            `key='{user_key}'`.\n\n            To fix this, please make sure that the `key` argument is unique for\n            each `st.{widget_type}` you create.\n            \"\"\"\n        )\n    else:\n        message = textwrap.dedent(\n            \"\"\"\n            There are multiple identical `st.{widget_type}` widgets with the\n            same generated key.\n\n            (When a widget is created, it's assigned an internal key based on\n            its structure. Multiple widgets with an identical structure will\n            result in the same internal key, which causes this error.)\n\n            To fix this, please pass a unique `key` argument to\n            `st.{widget_type}`.\n            \"\"\"\n        )\n\n    return message.strip(\"\\n\").format(widget_type=widget_func_name, user_key=user_key)\n\n\ndef _set_widget_id(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> None:\n    \"\"\"Set the widget id.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element_proto : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str or None\n        Optional user-specified key to use for the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    \"\"\"\n\n    if widget_func_name is None:\n        widget_func_name = element_type\n\n    # Identify the widget with a hash of type + contents\n    element_hash = hash((element_type, element_proto.SerializeToString()))\n    if user_key is not None:\n        widget_id = \"%s-%s\" % (user_key, element_hash)\n    else:\n        widget_id = \"%s\" % element_hash\n\n    ctx = get_report_ctx()\n    if ctx is not None:\n        added = ctx.widget_ids_this_run.add(widget_id)\n        if not added:\n            raise DuplicateWidgetID(\n                _build_duplicate_widget_message(widget_func_name, user_key)\n            )\n    element_proto.id = widget_id\n\n\ndef _get_widget_ui_value(\n    element_type: str,\n    element_proto: Any,\n    user_key: Optional[str] = None,\n    widget_func_name: Optional[str] = None,\n) -> Any:\n    \"\"\"Get the widget ui_value from the report context.\n    NOTE: This function should be called after the proto has been filled.\n\n    Parameters\n    ----------\n    element_type : str\n        The type of the element as stored in proto.\n    element : proto\n        The proto of the specified type (e.g. Button/Multiselect/Slider proto)\n    user_key : str\n        Optional user-specified string to use as the widget ID.\n        If this is None, we'll generate an ID by hashing the element.\n    widget_func_name : str or None\n        The widget's DeltaGenerator function name, if it's different from\n        its element_type. Custom components are a special case: they all have\n        the element_type \"component_instance\", but are instantiated with\n        dynamically-named functions.\n\n    Returns\n    -------\n    ui_value : any\n        The value of the widget set by the client or\n        the default value passed. If the report context\n        doesn't exist, None will be returned.\n\n    \"\"\"\n    _set_widget_id(element_type, element_proto, user_key, widget_func_name)\n    ctx = get_report_ctx()\n    ui_value = ctx.widgets.get_widget_value(element_proto.id) if ctx else None\n    return ui_value\n\n\ndef last_index_for_melted_dataframes(data):\n    if type_util.is_dataframe_compatible(data):\n        data = type_util.convert_anything_to_df(data)\n\n        if data.index.size > 0:\n            return data.index[-1]\n\n    return None\n", "path": "lib/streamlit/elements/utils.py"}]}