{"record":{"id":"1b19b71d2fd6617d","repo":"vitessio/vitess","slug":"unable-to-delete-file-v","errorCode":null,"errorMessage":"unable to delete file: %v","messagePattern":"unable to delete file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/backupengine.go","lineNumber":776,"sourceCode":"\t// change Create to Open\n\t// rename func to openStateFile\n\t// change to return a *File\n\tfname := filepath.Join(cnf.TabletDir(), RestoreState)\n\tfd, err := os2.Create(fname)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create file: %v\", err)\n\t}\n\tif err = fd.Close(); err != nil {\n\t\treturn fmt.Errorf(\"unable to close file: %v\", err)\n\t}\n\treturn nil\n}\n\n// delete restore state file\nfunc removeStateFile(cnf *Mycnf) error {\n\tfname := filepath.Join(cnf.TabletDir(), RestoreState)\n\tif err := os.Remove(fname); err != nil {\n\t\treturn fmt.Errorf(\"unable to delete file: %v\", err)\n\t}\n\treturn nil\n}\n\n// RestoreWasInterrupted tells us whether a previous restore\n// was interrupted and we are now retrying it\nfunc RestoreWasInterrupted(cnf *Mycnf) bool {\n\tname := filepath.Join(cnf.TabletDir(), RestoreState)\n\t_, err := os.Stat(name)\n\treturn err == nil\n}\n\n// GetBackupDir returns the directory where backups for the\n// given keyspace/shard are (or will be) stored\nfunc GetBackupDir(keyspace, shard string) string {\n\treturn fmt.Sprintf(\"%v/%v\", keyspace, shard)\n}\n","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/backupengine.go#L758-L794","documentation":"removeStateFile deletes the restore state file from the tablet directory after a successful restore. If os.Remove fails for any reason (missing file, permissions, I/O error), the underlying error is wrapped with this message. It signals that leftover restore state could not be cleaned up, which may make the next restore think a previous one was interrupted.","triggerScenarios":"Called during restore cleanup in mysqlctl; os.Remove fails on <TabletDir>/<RestoreState> because the file is absent, the vitess user lacks write permission on the tablet directory, or the filesystem reports an I/O error.","commonSituations":"Tablet directory ownership/permissions wrong after running as different user; state file already removed by concurrent cleanup; disk full or read-only mount after a crash.","solutions":["Check that the tablet directory is writable by the process user (ls -ld on the tablet dir).","Verify whether the state file exists; if it is simply missing, treat cleanup as done (skip os.Remove when os.IsNotExist).","Inspect the wrapped %v error for the concrete errno (ENOENT vs EACCES vs EIO) and fix accordingly.","Rerun the restore; the state file is only leftover state, not data."],"exampleFix":"// before\nif err := os.Remove(fname); err != nil {\n\treturn fmt.Errorf(\"unable to delete file: %v\", err)\n}\n// after\nif err := os.Remove(fname); err != nil && !os.IsNotExist(err) {\n\treturn fmt.Errorf(\"unable to delete file %s: %w\", fname, err)\n}\nreturn nil","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(fname); err == nil {\n\tif err := os.Remove(fname); err != nil {\n\t\treturn fmt.Errorf(\"unable to delete file %s: %w\", fname, err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err := removeStateFile(cnf); err != nil {\n\tlog.Warn(\"restore state file cleanup failed\", slog.Any(\"error\", err))\n\t// non-fatal: next restore will see RestoreWasInterrupted and clean up\n}","preventionTips":["Ensure the tablet directory is owned by the user running vitess processes.","Treat ENOENT on cleanup paths as success, not failure.","Monitor disk health; EIO on unlink usually precedes bigger filesystem problems."],"tags":["filesystem","mysqlctl","restore"],"backgroundTag":"file-delete-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}