risingwavelabs/risingwave · error

`SHOW BINARY LOGS`: missing `File_size` column

Error message

`SHOW BINARY LOGS`: missing `File_size` column

What it means

Companion to error 966: row column 1 of `SHOW BINARY LOGS` must be the file size (`File_size`), decoded as u64. A NULL/missing value in that column triggers this error while mapping binlog files for metrics and split planning.

Solutions

  1. Run `SHOW BINARY LOGS` manually with the same credentials and confirm File_size is populated.
  2. Bypass any proxy/intermediary and connect to the actual MySQL server.
  3. Use a supported MySQL version/build (5.7/8.0 standard) for the CDC source.
  4. If a specific binlog row is NULL, run PURGE BINARY LOGS / check server binlog state and restart the source.
Defensive patterns

Strategy: try-catch

Validate before calling

// verify File_size is populated before enabling CDC monitoring
let ok = sqlx::query("SHOW BINARY LOGS").fetch_all(&pool).await?
    .iter().all(|row| !row.try_get::<Option<u64>, _>(1)?.is_none());
assert!(ok, "File_size column NULL in SHOW BINARY LOGS");

Try / catch

if let Err(e) = res {
    if e.to_string().contains("missing `File_size`") {
        log::warn!("binlog row without size; inspect server binlog state / purge old logs");
        tokio::time::sleep(BACKOFF).await;
    }
}

Prevention

When it happens

Trigger: `SHOW BINARY LOGS` result rows have a NULL second column when query_binlog_files maps rows to (filename, size) pairs.

Common situations: MySQL-compatible middleware altering the statement's column set, corrupted/rotated binlog entries reported oddly by a non-standard server, or a stripped result set from a limited-privilege account via a proxy.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/81fc3314e3580bbb. Report an issue: GitHub.

Appendix: source

Thrown at src/connector/src/source/cdc/enumerator/mod.rs:553

        // only return the first 2. Decode the row manually so we don't panic on column-count
        // differences.
        let rows: Vec<Row> = conn
            .query("SHOW BINARY LOGS")
            .await
            .context("failed to execute `SHOW BINARY LOGS`")?;
        let query_result = rows
            .into_iter()
            .map(|mut row| -> ConnectorResult<(String, u64)> {
                let log_name = row
                    .take_opt::<String, _>(0)
                    .transpose()
                    .context("`SHOW BINARY LOGS`: failed to decode `Log_name`")?
                    .ok_or_else(|| anyhow!("`SHOW BINARY LOGS`: missing `Log_name` column"))?;
                let file_size = row
                    .take_opt::<u64, _>(1)
                    .transpose()
                    .context("`SHOW BINARY LOGS`: failed to decode `File_size`")?
                    .ok_or_else(|| anyhow!("`SHOW BINARY LOGS`: missing `File_size` column"))?;
                Ok((log_name, file_size))
            })
            .collect::<ConnectorResult<Vec<_>>>()?;

        drop(conn);
        pool.disconnect().await.ok();

        Ok(query_result)
    }
}

impl ListCdcSplits for DebeziumSplitEnumerator<Mysql> {
    type CdcSourceType = Mysql;

    fn list_cdc_splits(&mut self) -> Vec<DebeziumCdcSplit<Self::CdcSourceType>> {
        // CDC source only supports single split
        vec![DebeziumCdcSplit::<Self::CdcSourceType>::new(
            self.source_id.as_raw_id(),

View on GitHub (pinned to 6469eb736d)