vitessio/vitess · error
unable to create file: %v
Error message
unable to create file: %v
What it means
Thrown by createStateFile (restore preparation) when os2.Create fails on the restore state file at <tabletDir>/restore_state. The state file marks that a restore is in progress so a crash mid-restore can be detected; failure usually means the tablet directory is missing or the filesystem is unwritable.
Source
Thrown at go/vt/mysqlctl/backupengine.go:764
logger.Infof("Restore: reinit config file")
if err := mysqld.ReinitConfig(ctx, cnf); err != nil {
return err
}
return nil
}
// create restore state file
func createStateFile(cnf *Mycnf) error {
// if we start writing content to this file:
// change RD_ONLY to RDWR
// change Create to Open
// rename func to openStateFile
// change to return a *File
fname := filepath.Join(cnf.TabletDir(), RestoreState)
fd, err := os2.Create(fname)
if err != nil {
return fmt.Errorf("unable to create file: %v", err)
}
if err = fd.Close(); err != nil {
return fmt.Errorf("unable to close file: %v", err)
}
return nil
}
// delete restore state file
func removeStateFile(cnf *Mycnf) error {
fname := filepath.Join(cnf.TabletDir(), RestoreState)
if err := os.Remove(fname); err != nil {
return fmt.Errorf("unable to delete file: %v", err)
}
return nil
}
// RestoreWasInterrupted tells us whether a previous restore
// was interrupted and we are now retrying itView on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure the tablet directory exists and is writable by the process user (mkdir/chown/chmod as needed).
- Read the wrapped OS error for the concrete cause (ENOENT, EACCES, EROFS, ENOSPC) and fix that specific condition.
- Check disk space on the volume holding the tablet dir.
- Verify the tablet_dir path configuration points at the intended location.
Example fix
// before: dir missing -> "unable to create file: open /vt/vtdataroot/vt_0000000100/restore_state: no such file or directory" mkdir -p /vt/vtdataroot/vt_0000000100 && chown vitess:vitess /vt/vtdataroot/vt_0000000100 // after: restore proceeds
Defensive patterns
Strategy: validation
Validate before calling
dir := cnf.TabletDir()
if st, err := os.Stat(dir); err != nil || !st.IsDir() {
return fmt.Errorf("tablet dir %s missing or not a directory", dir)
}
probe := filepath.Join(dir, ".write_probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil {
return fmt.Errorf("tablet dir not writable: %w", err)
}
os.Remove(probe) Try / catch
if err := restore(); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && (errors.Is(pe.Err, fs.ErrPermission) || errors.Is(pe.Err, fs.ErrNotExist)) {
// fix tablet dir permissions/existence, then retry restore
}
return err
} Prevention
- Initialize the tablet directory before restore.
- Run the restore process as the user owning the tablet dir.
- Monitor disk space on the vtdataroot volume.
- Keep restore volumes read-write; check mount flags.
When it happens
Trigger: Restore flow calls createStateFile; the OS returns an error creating the file — tablet dir does not exist, wrong permissions/ownership, read-only filesystem, or disk full.
Common situations: Tablet directory deleted or never initialized before restore; mounted restore volume is read-only; running mysqlctl/vttablet as a user lacking write access to the tablet dir; ENOSPC on a full disk.
Related errors
- unable to close file: %v
- cannot stat hook %v: %v
- unable to delete file: %v
- could not create temp file: %v
- could not read existing file %v: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/810dbd47c61c6ffd.
Report an issue: GitHub.