vitessio/vitess · error

could not read existing file

Error message

could not read existing file %v: %v

What it means

Returned by mysqld config update logic when the existing (current) config file on disk cannot be read before applying updates, wrapping the I/O error.

Solutions

  1. Verify cnf.Path exists and is readable by the current user.
  2. If my.cnf was intentionally removed, reinitialize the tablet config instead of refreshing.
  3. Fix permissions: chown/chmod the my.cnf file.
  4. Point cnf.Path at the correct config location for this tablet.

Example fix

// before
rm /vt/vtdataroot/vt_0000000100/my.cnf  # then RefreshConfig fails
// after
vttablet reinit (or restore my.cnf from my.cnf.previous) before refreshing
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(cnf.Path); err != nil {
    return fmt.Errorf("existing my.cnf %s missing; reinit required before refresh", cnf.Path)
}

Try / catch

if err := mysqld.RefreshConfig(ctx, cnf); err != nil {
    if strings.Contains(err.Error(), "could not read existing file") {
        log.Errorf("my.cnf absent/unreadable at %s; reinitialize config", cnf.Path)
    }
    return err
}

Prevention

When it happens

Trigger: Mysqld.RefreshConfig after successfully writing the temp config: os.ReadFile(cnf.Path) fails because my.cnf was deleted, moved, or has bad permissions.

Common situations: First-time refresh before my.cnf ever written in an unexpected code path; manual cleanup removed my.cnf; tablet directory partially deleted; user running refresh differs from owner of my.cnf.

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/b9ca5f0231df91fe. Report an issue: GitHub.

Appendix: source

Thrown at go/vt/mysqlctl/mysqld.go:1581

		defer client.Close()
		return client.RefreshConfig(ctx)
	}

	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 {

View on GitHub (pinned to 01a25a7d17)