vitessio/vitess · error
could not read updated file %v: %v
Error message
could not read updated file %v: %v
What it means
Returned by mysqld config update logic when the newly written/updated config file cannot be read back for verification, wrapping the I/O error.
Source
Thrown at go/vt/mysqlctl/mysqld.go:1585
log.Info("Checking for updates to my.cnf")
f, err := os.CreateTemp(path.Dir(cnf.Path), "my.cnf")
if err != nil {
return fmt.Errorf("could not create temp file: %v", err)
}
defer os.Remove(f.Name())
err = mysqld.initConfig(cnf, f.Name())
if err != nil {
return fmt.Errorf("could not initConfig in %v: %v", f.Name(), err)
}
existing, err := os.ReadFile(cnf.Path)
if err != nil {
return fmt.Errorf("could not read existing file %v: %v", cnf.Path, err)
}
updated, err := os.ReadFile(f.Name())
if err != nil {
return fmt.Errorf("could not read updated file %v: %v", f.Name(), err)
}
if bytes.Equal(existing, updated) {
log.Info("No changes to my.cnf. Continuing.")
return nil
}
backupPath := cnf.Path + ".previous"
err = os.Rename(cnf.Path, backupPath)
if err != nil {
return fmt.Errorf("could not back up existing %v: %v", cnf.Path, err)
}
err = os.Rename(f.Name(), cnf.Path)
if err != nil {
return fmt.Errorf("could not move %v to %v: %v", f.Name(), cnf.Path, err)
}
log.Info(fmt.Sprintf("Updated my.cnf. Backup of previous version available in %v", backupPath))
View on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure only one RefreshConfig runs at a time for a given tablet.
- Check that the temp directory isn't subject to aggressive cleanup while refresh runs.
- Re-run RefreshConfig; if it recurs, inspect initConfig's write path for errors.
Example fix
// before: concurrent refreshes refreshConfig() && refreshConfig() // second reads removed temp file // after: serialize per tablet mu.Lock(); defer mu.Unlock(); refreshConfig()
Defensive patterns
Strategy: retry
Try / catch
err := mysqld.RefreshConfig(ctx, cnf)
for i := 0; i < 3 && err != nil && strings.Contains(err.Error(), "could not read updated file"); i++ {
time.Sleep(time.Second)
err = mysqld.RefreshConfig(ctx, cnf)
} Prevention
- Serialize RefreshConfig per tablet (single-flight/mutex)
- Exclude vitess config dirs from tmp-cleanup daemons
- Avoid external jobs that sweep temp files during tablet lifecycle
- Alert on repeated refresh failures — they indicate a race
When it happens
Trigger: Mysqld.RefreshConfig: os.ReadFile(f.Name()) fails after initConfig — temp file deleted concurrently, or was never written due to a silent failure.
Common situations: Another process cleaned /tmp or the config dir concurrently; deferred cleanup racing in overlapping RefreshConfig calls; antivirus/cleanup daemon removing temp files.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to create file-based writer for --opentsdb-uri %s: %v
- missing file on disk: %s (%w)
- cannot stat hook %v: %v
- unable to create file: %v
- unable to close file: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/f85253aefb50287a.
Report an issue: GitHub.