getredash/redash · error · Exception
Missing `rows` field in `result` dict.
Error message
Missing `rows` field in `result` dict.
What it means
Raised by PythonQueryRunner.validate_result (redash/query_runner/python.py:323) when the user-supplied query script builds a `result` dict that has no `rows` key. Redash's Python query runner executes the user's code, then requires the contract that `result` be a non-empty dict containing both `rows` and `columns` lists before the data can be rendered. This error means the script completed but did not assign query results into the expected shape.
Source
Thrown at redash/query_runner/python.py:323
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")
builtins = safe_builtins.copy()
builtins["_write_"] = self.custom_write
builtins["__import__"] = self.custom_importView on GitHub (pinned to ca79fe988d)
Solutions
- Add a `rows` key holding a list of dict records to the `result` variable, e.g. `result = {'rows': [...], 'columns': [...]}`
- Also include `columns` as a list of column definitions to avoid the next validation failure
- If using pandas, convert with `result = {'columns': [{'name': c, 'friendly_name': c} for c in df.columns], 'rows': df.to_dict(orient='records')}`
Example fix
# before
result = {'columns': [{'name': 'id'}]}
# after
result = {'columns': [{'name': 'id'}], 'rows': [{'id': 1}, {'id': 2}]} Defensive patterns
Strategy: validation
Validate before calling
result = build_result() # from user script
if 'rows' not in result:
raise ValueError('script must define result["rows"]') Type guard
def is_valid_result(r) -> bool:
return (
isinstance(r, dict) and bool(r)
and isinstance(r.get('rows'), list)
and isinstance(r.get('columns'), list)
) Try / catch
try:
validate_result(result)
except Exception as e:
raise UserFacingError('Python query output invalid: {}'.format(e)) Prevention
- Standardize a helper that builds result = {'columns': [...], 'rows': [...]} in all Python queries
- Write the rows assignment as the last statement of the script
- Use df.to_dict(orient='records') for pandas so rows is always a list of dicts
When it happens
Trigger: Running a Python-type query in Redash whose code sets `result = {...}` (or mutates a result dict) without ever putting a `rows` key in it, e.g. `result = {'columns': [...]}` or `result = {'data': ...}`.
Common situations: Users porting pandas/scratch scripts to Redash and returning a DataFrame or arbitrary payload instead of the rows/columns dict; typos like `result['row'] = ...`; forgetting the final `result` assignment entirely (which hits the earlier empty check instead).
Related errors
- Missing `columns` field in `result` dict.
- `rows` field should be of type `list`.
- `columns` field should be of type `list`.
- Query id {} not found.
- Queries of type {} can not be processed by redash.
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/f60715d26caaaf09.
Report an issue: GitHub.