-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Environment
- Django Debug Toolbar: 6.2.0 (also reproduced on 6.1.0)
- Python: 3.12
- Django: 5.2
Error
File "debug_toolbar/store.py", in save_panel
cls._request_store[request_id][panel_id] = serialize(data)
File "debug_toolbar/store.py", in serialize
return json.dumps(data, cls=DebugToolbarJSONEncoder)
TypeError: keys must be str, int, float, bool or None, not tuple
Root cause?
DebugToolbarJSONEncoder.default() seems to handle non-serializable values via force_str, but Python's JSON C encoder raises TypeError for non-string dict keys before default() is ever invoked. I guess it's a known issue since store.py already has a comment describing this failure?
Affected panels
CachePanel - triggered when a cached value is a dict with non-string keys:
from uuid import UUID
from django.core.cache import cache
cache.set("my_key", {
(UUID("aaaaaaaa-0000-0000-0000-000000000001"), UUID("bbbbbbbb-0000-0000-0000-000000000002")): {"value": 1},
(UUID("dddddddd-0000-0000-0000-000000000004"), UUID("eeeeeeee-0000-0000-0000-000000000005")): {"value": 2},
}, timeout=300)_store_call_info captures the raw args tuple (including the dict value) into self.calls. When generate_stats serializes self.calls, json.dumps raises on the tuple keys inside that dict.
RequestPanel - triggered when a session value is a dict with non-string keys:
request.session["lookup"] = {(1, 2): "foo", (3, 4): "bar"}sanitize_and_sort_request_vars wraps the session in {"list": [...]} but passes dict values through unchanged, so the nested dict with tuple keys reaches serialize() and crashes.
Workaround
Exclude the affected panels in DEBUG_TOOLBAR_PANELS in Django settings.py:
DEBUG_TOOLBAR_PANELS = [
"debug_toolbar.panels.history.HistoryPanel",
"debug_toolbar.panels.versions.VersionsPanel",
"debug_toolbar.panels.timer.TimerPanel",
"debug_toolbar.panels.settings.SettingsPanel",
"debug_toolbar.panels.headers.HeadersPanel",
# "debug_toolbar.panels.request.RequestPanel",
"debug_toolbar.panels.sql.SQLPanel",
"debug_toolbar.panels.staticfiles.StaticFilesPanel",
"debug_toolbar.panels.templates.TemplatesPanel",
"debug_toolbar.panels.alerts.AlertsPanel",
# "debug_toolbar.panels.cache.CachePanel",
"debug_toolbar.panels.signals.SignalsPanel",
"debug_toolbar.panels.logging.LoggingPanel",
"debug_toolbar.panels.redirects.RedirectsPanel",
"debug_toolbar.panels.profiling.ProfilingPanel",
]