vitessio/vitess · error
INVALID_ARGUMENT
INVALID_ARGUMENT
Error message
empty binlog list in ReadBinlogFilesTimestampsRequest
What it means
ReadBinlogFilesTimestamps validates its request before doing any work: the request must name at least one binlog file. A nil response with INVALID_ARGUMENT is returned when req.BinlogFileNames is empty, because there is nothing to scan with `mysqlbinlog`.
Source
Thrown at go/vt/mysqlctl/mysqld.go:2207
return nil
}
if err := mysqlbinlogCmd.Start(); err != nil { // Start() is nonblockig
return firstMatchedTime, lastMatchedTime, err
}
defer mysqlbinlogCmd.Process.Kill()
if err := scan(); err != nil { // We must first exhaust reading the command's output, before calling cmd.Wait()
return firstMatchedTime, lastMatchedTime, vterrors.Wrapf(err, "scanning mysqlbinlog output in ReadBinlogFilesTimestamps")
}
if err := mysqlbinlogCmd.Wait(); err != nil {
return firstMatchedTime, lastMatchedTime, vterrors.Wrapf(err, "waiting on mysqlbinlog command in ReadBinlogFilesTimestamps")
}
return firstMatchedTime, lastMatchedTime, nil
}
// ReadBinlogFilesTimestamps reads all given binlog files via `mysqlbinlog` command and returns the first and last found transaction timestamps
func (mysqld *Mysqld) ReadBinlogFilesTimestamps(ctx context.Context, req *mysqlctlpb.ReadBinlogFilesTimestampsRequest) (*mysqlctlpb.ReadBinlogFilesTimestampsResponse, error) {
if len(req.BinlogFileNames) == 0 {
return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "empty binlog list in ReadBinlogFilesTimestampsRequest")
}
if socketFile != "" {
log.Info(fmt.Sprintf("executing Mysqld.ReadBinlogFilesTimestamps() remotely via mysqlctld server: %v", socketFile))
client, err := mysqlctlclient.New(ctx, "unix", socketFile)
if err != nil {
return nil, fmt.Errorf("can't dial mysqlctld: %v", err)
}
defer client.Close()
return client.ReadBinlogFilesTimestamps(ctx, req)
}
dir, err := vtenv.VtMysqlRoot()
if err != nil {
return nil, err
}
env, err := buildLdPaths()
if err != nil {
return nil, err
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Populate BinlogFileNames with the binlog files you want timestamps for before calling.
- Guard the call site with a length check and skip the operation entirely when no files exist.
- If an empty directory is legitimate, treat this error as a no-op signal rather than retrying.
Example fix
// before
res, err := mysqld.ReadBinlogFilesTimestamps(ctx, &mysqlctlpb.ReadBinlogFilesTimestampsRequest{
BinlogFileNames: files,
})
// after
if len(files) == 0 {
return nil // nothing to inspect
}
res, err := mysqld.ReadBinlogFilesTimestamps(ctx, &mysqlctlpb.ReadBinlogFilesTimestampsRequest{
BinlogFileNames: files,
}) Defensive patterns
Strategy: validation
Validate before calling
if len(req.GetBinlogFileNames()) == 0 {
return fmt.Errorf("refusing to call ReadBinlogFilesTimestamps with no binlog files")
} Type guard
func hasBinlogFiles(req *mysqlctlpb.ReadBinlogFilesTimestampsRequest) bool {
return req != nil && len(req.BinlogFileNames) > 0
} Try / catch
if !hasBinlogFiles(req) {
// skip timestamps collection entirely; nothing to do
} else if _, err := mysqld.ReadBinlogFilesTimestamps(ctx, req); err != nil {
return err
} Prevention
- Check the binlog directory listing length before building the request.
- Treat an empty binlog dir as a legitimate early-exit in backup/restore flows.
- Add unit tests for request-construction helpers covering the empty case.
When it happens
Trigger: Calling Mysqld.ReadBinlogFilesTimestamps(ctx, &mysqlctlpb.ReadBinlogFilesTimestampsRequest{}) or with BinlogFileNames: [] (zero-length list), either directly or via the mysqlctld RPC path.
Common situations: A backup/restore helper enumerating binlog files from an empty binlog directory; filtering logic that removes all files before building the request; new code paths constructing the request programmatically without checking length.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- GetPreviousGTIDs: previous GTIDs not found
- ErrPartSize
- BeforeSchema differs
- AfterSchema differs
- UUID values must be unique
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/beff30051db3aa12.
Report an issue: GitHub.