Dash 2.0.0 migration error - TypeError: '<' not supported between instances of 'str' and 'int'

After upgrading dash to 2.0.0 and updating the code to fix depreciation warnings, when I try to access my app I get a response that just says “Error loading layout”. The log file has the following unhelpful traceback (slightly redacted for proprietary information):

ERROR - 2021-09-09 11:19:22,662 - navigator.app - app - app.py - log_exception - 14052 - 26024 - Exception on /Developer Testing/App/1/_dash-layout [GET]
Traceback (most recent call last):
  File "c:\desktop\environment\python\lib\site-packages\flask\app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\desktop\environment\python\lib\site-packages\flask\app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\desktop\environment\python\lib\site-packages\flask\app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\desktop\environment\python\lib\site-packages\flask\app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "c:\desktop\environment\python\lib\site-packages\flask_login\utils.py", line 261, in decorated_view
    return func(*args, **kwargs)
  File "c:\desktop\environment\python\lib\site-packages\dash\dash.py", line 560, in serve_layout
    to_json(layout),
  File "c:\desktop\environment\python\lib\site-packages\dash\_utils.py", line 21, in to_json
    return to_json_plotly(value)
  File "c:\desktop\environment\python\lib\site-packages\plotly\io\_json.py", line 124, in to_json_plotly
    return json.dumps(plotly_object, cls=PlotlyJSONEncoder, **opts)
  File "c:\desktop\environment\python\lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "c:\desktop\environment\python\lib\site-packages\_plotly_utils\utils.py", line 59, in encode
    encoded_o = super(PlotlyJSONEncoder, self).encode(o)
  File "c:\desktop\environment\python\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "c:\desktop\environment\python\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
TypeError: '<' not supported between instances of 'str' and 'int'

I was able to resolve the issue by installing orjson. I was able to run another dash app successfully in 2.0.0 so the error must be caused by something specific to my large dash app, although I can’t figure out what could be causing it.

Thanks for reporting! Odd to see an error within the python json standard library. We have very extensive tests here, so surprising to see something slip through the cracks.

Any chance you can trim down your app into something you can share? There is some part of your app layout that isn’t serializing to JSON correctly.

Under the hood, we’re basically just calling:

json.dumps(component_tree, cls=plotly.utils.PlotlyJSONEncoder)

Where component_tree would be app.layout and whatever is returned from your callback.

So, if you can find the particular part of your “component_tree” that cause this issue that would be immensely helpful.

A post was split to a new topic: Issue with orjson

Hi Chris-

Thanks for the explanation of what’s happening under the hood! The issue is actually related to setting sort_keys=True, if you leave that parameter off then the serialization occurs successfully. That presumably points to an issue with how the keys are being sorted (see Issue 25457: json dump fails for mixed-type keys when sort_keys is specified - Python tracker). Here is an example of a DataTable which causes the error, I converted ids from ints to strings to see if that would help and it didn’t:

DataTable(id={'type': 'section', 'section_id': '1'}, 

          columns=[{'name': 'Input matrix', 'id': '2e73b990-3b25-48ef-ad9c-97e89984a4e0'}, 

                   {'name': '0', 'id': '0', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x0000027F754BC400>}, 

                   {'name': '1', 'id': '1', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x0000027F754BC400>}, 

                   {'name': '2', 'id': '2', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x0000027F754BC400>}, 

                   {'name': '3', 'id': '3', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x0000027F754BC400>}, 

                   {'name': '4', 'id': '4', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x0000027F754BC400>}], 

          data=[{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'id': '0'}, 

                {0: 6, 1: 7, 2: 8, 3: 2, 4: 400, 'id': '1'}, 

                {0: 80, 1: 0, 2: 9, 3: 10, 4: 11, 'id': '2'}, 

                {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'id': '3'}, 

                {0: 6, 1: 7, 2: 8, 3: 2, 4: 400, 'id': '4'}, 

                {0: 80, 1: 0, 2: 9, 3: 10, 4: 11, 'id': '5'}], 

          editable=False, row_selectable=False, style_as_list_view=True, style_cell={'fontSize': 14, 'font-family': 'sans-serif'}, style_table={'overflowX': 'auto'})

I haven’t been able to track down why this is failing. I did find that the plotly json encoder calls to_plotly_json() on the layout, this is the result of running that method:

{'props': 

    {'children': [Div(children=[Tabs(children=[Tab(children=[DataTable(id={'type': 'section', 'section_id': '1'}, 

                                                                       columns=[{'name': 'Input matrix', 'id': '4b59f19e-968b-4927-a17a-33d14be85532'}, 

                                                                                {'name': '0', 'id': '0', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x000001DA1F5FD470>}, 

                                                                                {'name': '1', 'id': '1', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x000001DA1F5FD470>}, 

                                                                                {'name': '2', 'id': '2', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x000001DA1F5FD470>}, 

                                                                                {'name': '3', 'id': '3', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x000001DA1F5FD470>}, 

                                                                                {'name': '4', 'id': '4', 'type': 'numeric', 'format': <dash.dash_table.Format.Format object at 0x000001DA1F5FD470>}], 

                                                                       data=[{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'id': '0'}, {0: 6, 1: 7, 2: 8, 3: 2, 4: 400, 'id': '1'}, {0: 80, 1: 0, 2: 9, 3: 10, 4: 11, 'id': '2'}], 

                                                                       editable=False, row_selectable=False, style_as_list_view=True, style_cell={'fontSize': 14, 'font-family': 'sans-serif'}, 

                                                                       style_table={'overflowX': 'auto'})], id="{'type': 'tab', 'page': 'unassigned', 'index': '0'}", label='Inputs', value='Inputs')], 

                                     id='selected_tab', value='Inputs')], style={'width': '90%', 'padding-left': '5%', 'font-family': 'sans-serif'})], 'className': 'container'}, 'type': 'Div', 'namespace': 'dash_html_components'}

Appreciate any additional thoughts on what specifically might be causing this. It would be prohibitively difficult to strip the app down to transmit, I think this is probably the best I can provide in the forum. Thanks!

Thanks @colins ! I’ve tried reproducing the error with your data but I’m still having trouble. Does this code raise an error for you?

import dash
from dash.dash_table import DataTable
import json
import plotly

print(dash.__version__)   # 2.0.0
print(plotly.__version__)  # 5.1.0


c = DataTable(
    columns=[
        {'name': 'Input matrix', 'id': '2e73b990-3b25-48ef-ad9c-97e89984a4e0'}, 
        {'name': '0', 'id': 0, 'type': 'numeric'}, 
        {'name': '1', 'id': 1, 'type': 'numeric'}, 
        {'name': '2', 'id': 2, 'type': 'numeric'}, 
        {'name': '3', 'id': 3, 'type': 'numeric'}, 
        {'name': '4', 'id': 4, 'type': 'numeric'}], 
    data=[
        {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'id': '0'}, 
        {0: 6, 1: 7, 2: 8, 3: 2, 4: 400, 'id': '1'}, 
        {0: 80, 1: 0, 2: 9, 3: 10, 4: 11, 'id': '2'}, 
        {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 'id': '3'}, 
        {0: 6, 1: 7, 2: 8, 3: 2, 4: 400, 'id': '4'}, 
        {0: 80, 1: 0, 2: 9, 3: 10, 4: 11, 'id': '5'}
    ],
    editable=False,
    row_selectable=False,
    style_as_list_view=True,
    style_cell={'fontSize': 14, 'font-family': 'sans-serif'},
    style_table={'overflowX': 'auto'}
)

json.dumps(c, cls=plotly.utils.PlotlyJSONEncoder)

Oh I see now. The command above works but this fails:

json.dumps(c, cls=plotly.utils.PlotlyJSONEncoder, sort_keys=True)

OK, here is a MWE now:

import pandas as pd
from plotly.io.json import to_json_plotly

df = pd.DataFrame({'a': [0], 1: [0]})
to_json_plotly(df.to_dict('records'))

(Turns out we’re using to_json_plotly in Dash now, we used to use json.dumps(c, cls=plotly.utils.PlotlyJSONEncoder) - My mistake!)

We’ll look into it!

Tracking in Handle serializing dicts with ints and strings · Issue #3380 · plotly/plotly.py · GitHub

Thanks for reducing the example I provided - I spent longer than I’d like to admit trying to slim it down and never managed to do it. Glad I was at least on the right track with converting the integers to strings to try to fix it.

I’ll watch the issue in case I can do anything to help. As always, thank you for this amazing software!

1 Like