vitessio/vitess · warning

malformed logfile name: %v

Error message

malformed logfile name: %v

What it means

logutil.purgeCreatedTimestamp parses glog-style log filenames, which have the form program.host.user.log.NAME.yyyymmdd-hhmmss.pid. The library throws this when the base name splits into fewer than 6 dot-separated parts, meaning the file does not follow the glog naming convention and no creation timestamp can be extracted.

Source

Thrown at go/vt/logutil/purge.go:55

)

// RegisterFlags installs logutil flags on the given FlagSet.
//
// `go/cmd/*` entrypoints should either use servenv.ParseFlags(WithArgs)? which
// calls this function, or call this function directly before parsing
// command-line arguments.
func RegisterFlags(fs *pflag.FlagSet) {
	utils.SetFlagDurationVar(fs, &keepLogsByCtime, "keep-logs", keepLogsByCtime, "keep logs for this long (using ctime) (zero to keep forever)")
	utils.SetFlagDurationVar(fs, &keepLogsByMtime, "keep-logs-by-mtime", keepLogsByMtime, "keep logs for this long (using mtime) (zero to keep forever)")
	utils.SetFlagDurationVar(fs, &purgeLogsInterval, "purge-logs-interval", purgeLogsInterval, "how often try to remove old logs")
}

// parse parses a file name (as used by glog) and returns its process
// name and timestamp.
func parseCreatedTimestamp(filename string) (timestamp time.Time, err error) {
	parts := strings.Split(filepath.Base(filename), ".")
	if len(parts) < 6 {
		return time.Time{}, fmt.Errorf("malformed logfile name: %v", filename)
	}
	return time.ParseInLocation("20060102-150405", parts[len(parts)-2], time.Now().Location())
}

func getModifiedTimestamp(filename string) (timestamp time.Time, err error) {
	fileInfo, err := os.Stat(filename)
	if err != nil {
		return time.Time{}, err
	}
	return fileInfo.ModTime(), nil
}

var levels = []string{"INFO", "ERROR", "WARNING", "FATAL"}

// purgeLogsOnce removes logfiles for program for dir, if their age
// relative to now is greater than [cm]timeDelta
func purgeLogsOnce(now time.Time, dir, program string, ctimeDelta time.Duration, mtimeDelta time.Duration) {
	current := make(map[string]bool)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Move or exclude non-glog-named files from the log directory being purged.
  2. Restore the original glog naming (program.host.user.log.NAME.yyyymmdd-hhmmss.pid) for files you want purged.
  3. Configure the purge tool's directory to a location containing only Vitess glog files.
  4. Check the failing filename in the error (%v) and rename/repair it or delete it.

Example fix

// before (in the purge dir)
vttablet.log.1            // malformed, triggers error
// after (rename to glog format)
vttablet.host.user.log.ERROR.20260901-120000.1234
Defensive patterns

Strategy: type-guard

Validate before calling

func isGlogFilename(name string) bool {
	return len(strings.Split(filepath.Base(name), ".")) >= 6
}

Type guard

func looksLikeGlogLog(filename string) bool {
	parts := strings.Split(filepath.Base(filename), ".")
	if len(parts) < 6 {
		return false
	}
	_, err := time.ParseInLocation("20060102-150405", parts[len(parts)-2], time.Local)
	return err == nil
}

Try / catch

ts, err := logutil.ParseCreatedTimestamp(f) // if exported, or guard before purge
if err != nil {
	log.Warn("skipping non-glog file", slog.String("file", f))
	continue
}

Prevention

When it happens

Trigger: purgeLogsOnce scanning a log directory that contains non-glog files (e.g. 'app.log', rotated files renamed by logrotate, hand-created symlinks or marker files), or filenames truncated/renamed so fewer than 6 segments remain.

Common situations: Log directories shared with non-Vitess tooling, logrotate renaming files ('.1', '.gz'), operators manually renaming logs to keep them, tmp files created by editors in the log dir.

Understand the failure class

Related errors


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