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
- Inspect the wrapped error: 2020/1153 suggests max_allowed_packet; 1969/3024 suggests a server-side timeout; 2006/2013 a dropped connection.
- Increase `max_allowed_packet` on the MySQL server if large rows are involved.
- Reduce result size: add LIMIT/pagination or filter columns instead of SELECT *.
- Raise `net_read_timeout`/`net_write_timeout` and LB idle timeouts for long fetches.
- 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
- Paginate or LIMIT large reads instead of streaming entire tables
- Raise max_allowed_packet if rows contain large BLOB/TEXT values
- Set LB/proxy idle timeouts above the longest expected fetch
- Avoid server-side max_execution_time shorter than your fetch duration
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
- No response body for SSE stream
- Could not connect to the database
- Error streaming get request from authed http client to {url}
- Failed to read repository archive: {e}
- Error executing query: {:?}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/77d1a68b31c1573c.
Report an issue: GitHub.