windmill-labs/windmill · error

Error fetching row: {:?}

Error message

Error fetching row: {:?}

What it means

In the MySQL executor's streaming loop, `result.next()` (row fetch) returned an error after iteration had already started, so the stream yields `Error fetching row` and stops. This differs from 1045: the query was accepted but the connection or result-set broke mid-stream.

Source

Thrown at backend/windmill-worker/src/mysql_executor.rs:106

                let mut conn = conn.lock().await;
                let mut result = match conn.exec_iter(query, statement_values).await.map_err(to_anyhow) {
                    Ok(result) => result,
                    Err(e) => {
                        yield Err(anyhow!("Error executing query: {:?}", e));
                        return;
                    }
                };
                loop {
                    let row = result.next().await;
                    match row {
                        Ok(Some(row)) => {
                            yield Ok(convert_row_to_value(row));
                        }
                        Ok(None) => {
                            break;
                        }
                        Err(e) => {
                            yield Err(anyhow!("Error fetching row: {:?}", e));
                            return;
                        }
                    }
                }
            };

            s3_stream_and_upload_with_logs(
                "MySQL",
                rows_stream.boxed(),
                s3,
                job_id,
                workspace_id,
                log_conn,
            )
            .await?;

            Ok(vec![to_raw_value(&s3.to_return_s3_obj())])
        } else {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Inspect the wrapped error: 2020/1153 suggests max_allowed_packet; 1969/3024 suggests a server-side timeout; 2006/2013 a dropped connection.
  2. Increase `max_allowed_packet` on the MySQL server if large rows are involved.
  3. Reduce result size: add LIMIT/pagination or filter columns instead of SELECT *.
  4. Raise `net_read_timeout`/`net_write_timeout` and LB idle timeouts for long fetches.
  5. Retry the job — if transient network, a rerun often succeeds.

Example fix

// before: fetching everything, breaks mid-stream
SELECT * FROM huge_table;
// after: batch the read
SELECT * FROM huge_table ORDER BY id LIMIT 10000 OFFSET 0;
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: estimate result size before streaming
// SELECT COUNT(*) FROM huge_table WHERE ...;  — bail out or paginate if too large

Try / catch

// wrap the streamed fetch with one retry on transient connection errors
async fn fetch_with_retry(q: &str) -> Result<Rows> {
    match fetch(q).await {
        Err(e) if is_transient(&e) => fetch(q).await,
        other => other,
    }
}

Prevention

When it happens

Trigger: While pulling rows from a large result set, the connection drops, the server kills the query (max_execution_time, net_write_timeout), or the packet exceeds max_allowed_packet (very wide/long rows).

Common situations: Selecting millions of rows over a flaky network; MySQL proxy/LB with an idle timeout shorter than the fetch; `max_allowed_packet` too small for large BLOB/TEXT values; server-side query timeout killing the cursor mid-fetch.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/77d1a68b31c1573c. Report an issue: GitHub.