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

  1. Ensure only one RefreshConfig runs at a time for a given tablet.
  2. Check that the temp directory isn't subject to aggressive cleanup while refresh runs.
  3. 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

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


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/f85253aefb50287a. Report an issue: GitHub.