getredash/redash · error · Exception
local variable `result` should not be empty.
Error message
local variable `result` should not be empty.
What it means
validate_result() enforces that the Python query's `result` variable is a non-empty dict containing 'rows' and 'columns'. This first check fires when result is None, an empty dict, 0, empty list, etc. — i.e. the user's script finished without producing a result payload.
Source
Thrown at redash/query_runner/python.py:319
return self._get_current_user().to_dict()
def _get_current_user(self):
user = getattr(self, "_current_user", None)
if user is None:
raise Exception("Python query helpers require a current user.")
return user
def test_connection(self):
pass
def validate_result(self, result):
"""Validate the result after executing the query.
Parameters:
:result dict: The result dict.
"""
if not result:
raise Exception("local variable `result` should not be empty.")
if not isinstance(result, dict):
raise Exception("local variable `result` should be of type `dict`.")
if "rows" not in result:
raise Exception("Missing `rows` field in `result` dict.")
if "columns" not in result:
raise Exception("Missing `columns` field in `result` dict.")
if not isinstance(result["rows"], list):
raise Exception("`rows` field should be of type `list`.")
if not isinstance(result["columns"], list):
raise Exception("`columns` field should be of type `list`.")
def run_query(self, query, user):
self._current_user = user
try:
error = None
code = compile_restricted(query, "<string>", "exec")View on GitHub (pinned to ca79fe988d)
Solutions
- Always initialize and populate `result = {'columns': [], 'rows': []}` at the end of the script, even with zero rows
- Ensure the code path that sets result is unconditional (move initialization to the top)
- When there's no data, still add columns via add_result_column and leave rows empty
Example fix
# before
if data:
result = {'columns': cols, 'rows': data}
# after
result = {'columns': [], 'rows': []}
if data:
result['rows'] = data
for c in cols:
add_result_column(result, c, c, 'string') Defensive patterns
Strategy: validation
Validate before calling
result = {'columns': [], 'rows': []} # initialize first
# ... populate unconditionally before script ends
assert isinstance(result, dict) and result Type guard
def result_ok(r) -> bool:
return isinstance(r, dict) and bool(r) and 'rows' in r and 'columns' in r Prevention
- Initialize result = {'columns': [], 'rows': []} at the top of every Python query
- Ensure no code path (except/early-exit) can skip populating result
When it happens
Trigger: A Python query that never assigns `result = {...}`, assigns it conditionally and a branch skipped it, or leaves it as an empty dict because no rows matched before add_result_column calls.
Common situations: Authors prototype scripts that print instead of building result; loops that populate result only when data exists and today's data is empty; early return/exception handling leaving result unset.
Related errors
- local variable `result` should be of type `dict`.
- '{0}' is not configured as a supported import module
- '{} is not supported inplace variable
- '{0}' is not a supported column type
- Wrong data source name/id: %s.
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/79fc2620f9ccaa69.
Report an issue: GitHub.