matryer/xbar · warning

bad interval value: %s

Error message

bad interval value: %s

What it means

parseInterval splits the interval token into a numeric part and unit suffix, then uses strconv.ParseInt on the numeric part. If the number does not parse, it returns defaultRefreshInterval and errors.Errorf("bad interval value: %s", valStr). ParseFilenameInterval then re-wraps this with the filename. The value part must be a plain base-10 integer.

Source

Thrown at pkg/plugins/refresh_interval.go:162

	return interval
}

func parseInterval(interval string) (RefreshInterval, error) {
	var (
		unit   string
		valStr string
	)
	switch {
	case strings.HasSuffix(interval, "ms"):
		unit = "ms"
		valStr = interval[:len(interval)-2]
	default:
		unit = string(interval[len(interval)-1])
		valStr = interval[:len(interval)-1]
	}
	val, err := strconv.ParseInt(valStr, 10, 64)
	if err != nil {
		return defaultRefreshInterval, errors.Errorf("bad interval value: %s", valStr)
	}
	switch unit {
	case "d": // turn days into hours
		return RefreshInterval{N: val, Unit: "days"}, nil
	case "h":
		return RefreshInterval{N: val, Unit: "hours"}, nil
	case "m":
		return RefreshInterval{N: val, Unit: "minutes"}, nil
	case "s":
		return RefreshInterval{N: val, Unit: "seconds"}, nil
	case "ms":
		return RefreshInterval{N: val, Unit: "milliseconds"}, nil
	default:
		return defaultRefreshInterval, errors.Errorf("bad interval unit: %s", string(unit))
	}
}

View on GitHub (pinned to d624239058)

Solutions

  1. Edit the plugin filename so the value is a bare integer: 1.5h -> 90m, 0.5d -> 12h
  2. If you control the input, strip whitespace and validate with a regexp like ^\d+(ms|d|h|m|s)$ before parsing/renaming
  3. Rely on the returned default interval (1 minute) if the file cannot be renamed and the error is non-fatal

Example fix

// before
// file: weather.1.5h.py -> bad interval value: 5.5h
iv, err := plugins.ParseFilenameInterval("weather.1.5h.py")
// after
// rename to weather.90m.py
iv, err := plugins.ParseFilenameInterval("weather.90m.py") // -> {90, minutes}
Defensive patterns

Strategy: type-guard

Validate before calling

var tokenRe = regexp.MustCompile(`^(\d+)(ms|[dhms])$`)
func intervalTokenValid(name string) bool {
    tok := lastDottedSegment(strings.TrimSuffix(name, ".stp"))
    return tok == "" || tokenRe.MatchString(tok)
}

Try / catch

iv, err := plugins.ParseFilenameInterval(filename)
if err != nil && strings.Contains(err.Error(), "bad interval value") {
    // value part was not an integer; fall back to default already returned
    iv = plugins.RefreshInterval{N: 1, Unit: "minutes"}
}

Prevention

When it happens

Trigger: ParseFilenameInterval on a filename whose interval token has a non-integer value: "weather.5m.py" mis-typed as "weather..m.py" (valStr "" fails), "weather.5.5m.py" (valStr "5.5"), or "weather.fivem.py" (valStr "five").

Common situations: Fractional intervals like 1.5h written into filenames; typos after manual renames; interval token accidentally including extra characters from the name; plugin authors writing 0-prefix or signed values like +5m (actually +5 parses fine, but spaces do not).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02). Data as JSON: /api/errors/a48a2e0fde4acc13. Report an issue: GitHub.