{"record":{"id":"f85253aefb50287a","repo":"vitessio/vitess","slug":"could-not-read-updated-file-v-v","errorCode":null,"errorMessage":"could not read updated file %v: %v","messagePattern":"could not read updated file (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/mysqlctl/mysqld.go","lineNumber":1585,"sourceCode":"\tlog.Info(\"Checking for updates to my.cnf\")\n\tf, err := os.CreateTemp(path.Dir(cnf.Path), \"my.cnf\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not create temp file: %v\", err)\n\t}\n\n\tdefer os.Remove(f.Name())\n\terr = mysqld.initConfig(cnf, f.Name())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not initConfig in %v: %v\", f.Name(), err)\n\t}\n\n\texisting, err := os.ReadFile(cnf.Path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not read existing file %v: %v\", cnf.Path, err)\n\t}\n\tupdated, err := os.ReadFile(f.Name())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not read updated file %v: %v\", f.Name(), err)\n\t}\n\n\tif bytes.Equal(existing, updated) {\n\t\tlog.Info(\"No changes to my.cnf. Continuing.\")\n\t\treturn nil\n\t}\n\n\tbackupPath := cnf.Path + \".previous\"\n\terr = os.Rename(cnf.Path, backupPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not back up existing %v: %v\", cnf.Path, err)\n\t}\n\terr = os.Rename(f.Name(), cnf.Path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not move %v to %v: %v\", f.Name(), cnf.Path, err)\n\t}\n\tlog.Info(fmt.Sprintf(\"Updated my.cnf. Backup of previous version available in %v\", backupPath))\n","sourceCodeStart":1567,"sourceCodeEnd":1603,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/mysqlctl/mysqld.go#L1567-L1603","documentation":"Returned by mysqld config update logic when the newly written/updated config file cannot be read back for verification, wrapping the I/O error.","triggerScenarios":"Mysqld.RefreshConfig: os.ReadFile(f.Name()) fails after initConfig — temp file deleted concurrently, or was never written due to a silent failure.","commonSituations":"Another process cleaned /tmp or the config dir concurrently; deferred cleanup racing in overlapping RefreshConfig calls; antivirus/cleanup daemon removing temp files.","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."],"exampleFix":"// before: concurrent refreshes\nrefreshConfig() && refreshConfig() // second reads removed temp file\n// after: serialize per tablet\nmu.Lock(); defer mu.Unlock(); refreshConfig()","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := mysqld.RefreshConfig(ctx, cnf)\nfor i := 0; i < 3 && err != nil && strings.Contains(err.Error(), \"could not read updated file\"); i++ {\n    time.Sleep(time.Second)\n    err = mysqld.RefreshConfig(ctx, cnf)\n}","preventionTips":["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"],"tags":["filesystem","temp-file","race"],"backgroundTag":"file-not-found","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}