{"record":{"id":"f60715d26caaaf09","repo":"getredash/redash","slug":"missing-rows-field-in-result-dict","errorCode":null,"errorMessage":"Missing `rows` field in `result` dict.","messagePattern":"Missing `rows` field in `result` dict\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"redash/query_runner/python.py","lineNumber":323,"sourceCode":"        if user is None:\n            raise Exception(\"Python query helpers require a current user.\")\n        return user\n\n    def test_connection(self):\n        pass\n\n    def validate_result(self, result):\n        \"\"\"Validate the result after executing the query.\n\n        Parameters:\n        :result dict: The result dict.\n        \"\"\"\n        if not result:\n            raise Exception(\"local variable `result` should not be empty.\")\n        if not isinstance(result, dict):\n            raise Exception(\"local variable `result` should be of type `dict`.\")\n        if \"rows\" not in result:\n            raise Exception(\"Missing `rows` field in `result` dict.\")\n        if \"columns\" not in result:\n            raise Exception(\"Missing `columns` field in `result` dict.\")\n        if not isinstance(result[\"rows\"], list):\n            raise Exception(\"`rows` field should be of type `list`.\")\n        if not isinstance(result[\"columns\"], list):\n            raise Exception(\"`columns` field should be of type `list`.\")\n\n    def run_query(self, query, user):\n        self._current_user = user\n\n        try:\n            error = None\n\n            code = compile_restricted(query, \"<string>\", \"exec\")\n\n            builtins = safe_builtins.copy()\n            builtins[\"_write_\"] = self.custom_write\n            builtins[\"__import__\"] = self.custom_import","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/python.py#L305-L341","documentation":"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.","triggerScenarios":"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': ...}`.","commonSituations":"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).","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')}`"],"exampleFix":"# before\nresult = {'columns': [{'name': 'id'}]}\n# after\nresult = {'columns': [{'name': 'id'}], 'rows': [{'id': 1}, {'id': 2}]}","handlingStrategy":"validation","validationCode":"result = build_result()  # from user script\nif 'rows' not in result:\n    raise ValueError('script must define result[\"rows\"]')","typeGuard":"def is_valid_result(r) -> bool:\n    return (\n        isinstance(r, dict) and bool(r)\n        and isinstance(r.get('rows'), list)\n        and isinstance(r.get('columns'), list)\n    )","tryCatchPattern":"try:\n    validate_result(result)\nexcept Exception as e:\n    raise UserFacingError('Python query output invalid: {}'.format(e))","preventionTips":["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"],"tags":["python","query-runner","validation","redash"],"backgroundTag":"query-result-validation","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}