Issue Summary

After upgrading from v8 to v10, some (but not all) dashboard accesses give a 500 internal server error because “GET /api/dashboards/xxxxx” does not have a ?legacy query and is not treated as slug.

When I access the same URL again, it works with legacy query without any problem. The python error message indicates that the error is because it is treated as an id and not an integer.

[26/Jul/2022:03:17:56 +0000] "GET /api/dashboards/w2378_--jk HTTP/1.1" 500 36 "https://xxxxxxx/dashboard/w2378_--jk" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
[26/Jul/2022:03:17:59 +0000] "GET /api/dashboards/w2378_--jk?legacy HTTP/1.1" 200 3472 "https://xxxxxx/dashboard/w2378_--jk" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
  • The log above is in Safari, but it also occurs in Windows+Chrome.
  • We do not know why the legacy query is not attached.

What we want to solve

  1. do you have any tips for a solution?
  2. is there any way to reconfigure an existing slug based dashboard to be id based?

error msg

server_1            | [SQL: SELECT dashboards.updated_at AS dashboards_updated_at, dashboards.created_at AS dashboards_created_at, dashboards.id AS dashboards_id, dashboards.version AS dashboards_version, dashboards.org_id AS dashboards_org_id, dashboards.slug AS dashboards_slug, dashboards.name AS dashboards_name, dashboards.user_id AS dashboards_user_id, dashboards.layout AS dashboards_layout, dashboards.dashboard_filters_enabled AS dashboards_dashboard_filters_enabled, dashboards.is_archived AS dashboards_is_archived, dashboards.is_draft AS dashboards_is_draft, dashboards.tags AS dashboards_tags, dashboards.options AS dashboards_options
server_1            | FROM dashboards
server_1            | WHERE dashboards.id = %(id_1)s AND %(param_1)s = dashboards.org_id]
server_1            | [parameters: {'id_1': 'w2378_--jk', 'param_1': 1}]
server_1            | (Background on this error at: http://sqlalche.me/e/9h9h)
server_1            | [2022-07-26 03:17:53,035][PID:65][INFO][metrics] method=GET path=/api/dashboards/w2378_--jk endpoint=dashboard status=500 content_type=application/json content_length=36 duration=7.53 query_count=3 query_duration=9.62
server_1            | [2022-07-26 03:17:54,107][PID:57][ERROR][redash.app] Exception on /api/dashboards/w2378_--jk [GET]
server_1            | Traceback (most recent call last):
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1249, in _execute_context
server_1            |     cursor, statement, parameters, context
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 580, in do_execute
server_1            |     cursor.execute(statement, parameters)
server_1            | psycopg2.errors.InvalidTextRepresentation: invalid input syntax for integer: "w2378_--jk"
server_1            | LINE 3: WHERE dashboards.id = 'w2378_--jk' AND 1 = dash...
server_1            |                               ^
server_1            |
server_1            |
server_1            | The above exception was the direct cause of the following exception:
server_1            |
server_1            | Traceback (most recent call last):
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
server_1            |     rv = self.dispatch_request()
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
server_1            |     return self.view_functions[rule.endpoint](**req.view_args)
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask_restful/__init__.py", line 458, in wrapper
server_1            |     resp = resource(*args, **kwargs)
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask_login/utils.py", line 261, in decorated_view
server_1            |     return func(*args, **kwargs)
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask/views.py", line 89, in view
server_1            |     return self.dispatch_request(*args, **kwargs)
server_1            |   File "/app/redash/handlers/base.py", line 33, in dispatch_request
server_1            |     return super(BaseResource, self).dispatch_request(*args, **kwargs)
server_1            |   File "/usr/local/lib/python3.7/site-packages/flask_restful/__init__.py", line 573, in dispatch_request
server_1            |     resp = meth(*args, **kwargs)
server_1            |   File "/app/redash/permissions.py", line 71, in decorated
server_1            |     return fn(*args, **kwargs)
server_1            |   File "/app/redash/handlers/dashboards.py", line 195, in get
server_1            |     dashboard = get_object_or_404(fn, dashboard_id, self.current_org)
server_1            |   File "/app/redash/handlers/base.py", line 74, in get_object_or_404
server_1            |     rv = fn(*args, **kwargs)
server_1            |   File "/app/redash/models/mixins.py", line 28, in get_by_id_and_org
server_1            |     return query.one()
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3300, in one
server_1            |     ret = self.one_or_none()
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3269, in one_or_none
server_1            |     ret = list(self)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3342, in __iter__
server_1            |     return self._execute_and_instances(context)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3367, in _execute_and_instances
server_1            |     result = conn.execute(querycontext.statement, self._params)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 988, in execute
server_1            |     return meth(self, multiparams, params)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
server_1            |     return connection._execute_clauseelement(self, multiparams, params)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
server_1            |     distilled_params,
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1253, in _execute_context
server_1            |     e, statement, parameters, cursor, context
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1473, in _handle_dbapi_exception
server_1            |     util.raise_from_cause(sqlalchemy_exception, exc_info)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 398, in raise_from_cause
server_1            |     reraise(type(exception), exception, tb=exc_tb, cause=cause)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 152, in reraise
server_1            |     raise value.with_traceback(tb)
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1249, in _execute_context
server_1            |     cursor, statement, parameters, context
server_1            |   File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 580, in do_execute
server_1            |     cursor.execute(statement, parameters)
server_1            | sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input syntax for integer: "w2378_--jk"
server_1            | LINE 3: WHERE dashboards.id = 'w2378_--jk' AND 1 = dash...

Codes examined.

I looked at the code below, but I couldn’t figure out how the process is adding a LEGACY query.

Technical details:

  • Redash Version:8.0.0.b32245 → 10.1.0.b50633
  • Browser/OS: Chrome 103 / Windows10
  • How did you install Redash: official docker image / Amazon EC2

Thank you.

Sorry for the confusion. This is expected and is mentioned in the release notes for V10:

Dashboard URL Changes

Dashboard URLs now include the dashboard id and slug.

For example, given a dashboard with the slug account-overview and an id of 251:

Before
https://redash.app/dashboards/account-overview

After
https://redash.app/dashboards/251-account-overview

The dashboard can also be reached using the new /dashboard (notice this is singular) endpoint. It accepts either an ID or a slug:

  • https://redash.app/dashboard/251
  • https://redash.app/dashboard/account-overview

Either of these will redirect to the After link above. Dashboard ID’s are guaranteed to be unique. But dashboards can share the same slug. If a user visits /dashboard/<some slug> and more than one dashboard exists with that slug, they will be redirected to the earliest created dashboard with that slug.


  1. is there any way to reconfigure an existing slug based dashboard to be id based?

Visit the dashboard using the /dashboard endpoint, and update your bookmarks to the version with the integer id included.

1 Like

Visit the dashboard using the /dashboard endpoint, and update your bookmarks to the version with the integer id included.

Thank you very much. I will try this way.

1 Like