{"record":{"id":"be74e2f04e468076","repo":"risingwavelabs/risingwave","slug":"failed-to-get-row-stream-from-mysql-query","errorCode":null,"errorMessage":"failed to get row stream from mysql query","messagePattern":"failed to get row stream from mysql query","errorType":"exception","errorClass":"BatchError","httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/mysql_query.rs","lineNumber":124,"sourceCode":"            .tcp_port(self.port.parse::<u16>().unwrap()) // FIXME\n            .user(Some(self.username))\n            .pass(Some(self.password))\n            .db_name(Some(self.database))\n            .into();\n\n        let pool = mysql_async::Pool::new(database_opts);\n        let mut conn = pool\n            .get_conn()\n            .await\n            .context(\"failed to connect to mysql in batch executor\")?;\n\n        let query = self.query;\n        let mut query_iter = conn\n            .query_iter(query)\n            .await\n            .context(\"failed to execute my_sql_query in batch executor\")?;\n        let Some(row_stream) = query_iter.stream::<mysql_async::Row>().await? else {\n            bail!(\"failed to get row stream from mysql query\")\n        };\n\n        let mut builder = DataChunkBuilder::new(self.schema.data_types(), self.chunk_size);\n        tracing::debug!(\"mysql_query_executor: query executed, start deserializing rows\");\n        // deserialize the rows\n        #[for_await]\n        for row in row_stream {\n            let row = row?;\n            let owned_row = mysql_row_to_owned_row(row, &self.schema)?;\n            if let Some(chunk) = builder.append_one_row(owned_row) {\n                yield chunk;\n            }\n        }\n        if let Some(chunk) = builder.consume_all() {\n            yield chunk;\n        }\n        return Ok(());\n    }","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/mysql_query.rs#L106-L142","documentation":"In the MySQL batch query executor, `mysql_async`'s `query_iter(...).stream::<Row>()` returned `None`, meaning the connection did not yield a binary/text row stream for the executed statement (e.g. the statement produced no rowset). Since the executor expects result rows for the query, it fails with this error.","triggerScenarios":"Executing a batch MySQL external-table query where the statement does not return a row stream — e.g. the query was rewritten or routed to a statement that returns no resultset (non-SELECT), or the server closed/reset the result set.","commonSituations":"MySQL proxy/middleware (e.g. ProxySQL, MaxScale) interfering with result-set streaming; server-side errors surfaced as empty streams; pointing a RisingWave MySQL external table at a non-query endpoint or using a driver/proxy version mismatch.","solutions":["Verify the generated query returns a result set by running it directly against MySQL with the same credentials.","Check for proxies/load balancers between RisingWave and MySQL and test with a direct connection.","Confirm the MySQL user has SELECT privileges and the server supports streaming results (binary protocol).","Check the MySQL server error log for aborted statements around the time of the failure."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"-- run the expected query manually before wiring the external table\nSELECT 1 FROM information_schema.tables WHERE table_schema = 'db' AND table_name = 't';\n-- then run the actual query shape to confirm it returns a result set","typeGuard":null,"tryCatchPattern":"// wrap batch query execution and classify the failure\nmatch executor.execute().await {\n    Err(e) if e.to_string().contains(\"failed to get row stream from mysql query\") => {\n        // check query returns a result set; verify proxy/privileges; retry with direct connection\n    }\n    other => other?,\n}","preventionTips":["Test the exact query shape directly against MySQL with the same credentials before wiring it into RisingWave.","Avoid MySQL proxies/middleware in the data path, or verify streaming (binary protocol) works through them.","Grant the RisingWave MySQL user explicit SELECT privileges on the queried tables.","Monitor MySQL server logs for aborted statements or connection resets."],"tags":["batch-executor","mysql","external-table","network"],"backgroundTag":"database-query-failed","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}