{"record":{"id":"a612b798bd795d25","repo":"apache/superset","slug":"request-is-incorrect","errorCode":null,"errorMessage":"Request is incorrect","messagePattern":"Request is incorrect","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"superset/charts/data/api.py","lineNumber":725,"sourceCode":"            \"slice_id\": form_data.get(\"form_data\", {}).get(\"slice_id\"),\n        }\n\n    @logs_context(context_func=_map_form_data_datasource_to_dataset_id)\n    def _create_query_context_from_form(\n        self, form_data: dict[str, Any]\n    ) -> QueryContext:\n        \"\"\"\n        Create the query context from the form data.\n\n        :param form_data: The chart form data\n        :returns: The query context\n        :raises ValidationError: If the request is incorrect\n        \"\"\"\n\n        try:\n            return ChartDataQueryContextSchema().load(form_data)\n        except KeyError as ex:\n            raise ValidationError(\"Request is incorrect\") from ex\n\n    def _should_use_streaming(\n        self, result: dict[Any, Any], form_data: dict[str, Any] | None = None\n    ) -> bool:\n        \"\"\"Determine if streaming should be used based on actual row count threshold.\"\"\"\n        query_context = result[\"query_context\"]\n        result_format = query_context.result_format\n\n        # Only support CSV streaming currently\n        if result_format.lower() != \"csv\":\n            return False\n\n        # Get streaming threshold from config\n        threshold = app.config.get(\"CSV_STREAMING_ROW_THRESHOLD\", 100000)\n\n        # Extract actual row count (same logic as frontend)\n        actual_row_count: int | None = None\n        viz_type = form_data.get(\"viz_type\") if form_data else None","sourceCodeStart":707,"sourceCodeEnd":743,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/charts/data/api.py#L707-L743","documentation":"ValidationError('Request is incorrect') raised in ChartDataRestApi._run_create_query_context: loading the request payload through ChartDataQueryContextSchema raises a KeyError (typically from custom pre_load/field logic touching a dict key the payload does not contain, e.g. missing 'datasource' or a form_data sub-key), and the handler converts it into a generic 'Request is incorrect' validation error. It signals the form_data structure does not match what the chart-data API expects.","triggerScenarios":"POST /api/v1/chart/data with a payload missing required top-level keys such as 'datasource', 'queries' (or 'form_data' when using that shape), or with form_data whose nested keys (e.g. slice_id, datasource_id/datasource_name) are absent. Programmatic callers building payloads by hand instead of copying the shape the Explore UI sends are the usual source.","commonSituations":"Scripts that POST a minimal {'query': ...} payload assuming server-side defaults; frontend code paths that strip form_data keys; migrating clients from an older chart-data payload schema; embedding chart data calls where the payload was JSON-serialized from a partial object.","solutions":["Capture a working payload from the Explore UI (browser devtools, network tab) for the same chart and diff it against yours to find the missing key.","Ensure the payload contains 'datasource' (id + type) and a valid 'queries' array with all required fields per ChartDataQueryContextSchema.","If you only have classic form_data, send it under the documented form_data key so the schema's pre_load normalizes it.","Wrap the call and log the full rejected payload server-side (the original KeyError is chained via `from ex`) to identify the exact missing key."],"exampleFix":"# before\nrequests.post(\"/api/v1/chart/data\", json={\n    \"queries\": [{\"metrics\": [\"COUNT\"]}],   # no datasource -> KeyError -> Request is incorrect\n})\n\n# after\nrequests.post(\"/api/v1/chart/data\", json={\n    \"datasource\": {\"id\": 1, \"type\": \"table\"},\n    \"queries\": [{\"metrics\": [\"COUNT(*)\"], \"granularity\": None, \"groupby\": [], \"filters\": [], \"row_limit\": 100}],\n})","handlingStrategy":"validation","validationCode":"def payload_is_queryable(p: dict) -> bool:\n    datasource = p.get(\"datasource\")\n    queries = p.get(\"queries\")\n    return (\n        isinstance(datasource, dict)\n        and {\"id\", \"type\"} <= datasource.keys()\n        and isinstance(queries, list)\n        and len(queries) > 0\n    )\n\nassert payload_is_queryable(payload)","typeGuard":null,"tryCatchPattern":"from marshmallow import ValidationError\ntry:\n    resp = post_chart_data(payload)\nexcept ValidationError as ex:\n    if \"Request is incorrect\" in str(ex):\n        log.error(\"rejected payload: %s\", json.dumps(payload))  # diff vs a UI-captured payload\\n        raise","preventionTips":["Capture working payloads from the Explore UI network tab and template from them.","Validate for required keys (datasource{id,type}, non-empty queries) before POSTing to /api/v1/chart/data."],"tags":["rest-api","charts","validation","form-data","marshmallow"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}